def create_vpc_endpoint(client, module):
    params = dict()
    changed = False
    token_provided = False
    params['VpcId'] = module.params.get('vpc_id')
    params['ServiceName'] = module.params.get('service')
    params['DryRun'] = module.check_mode

    if module.params.get('route_table_ids'):
        params['RouteTableIds'] = module.params.get('route_table_ids')

    if module.params.get('client_token'):
        token_provided = True
        request_time = datetime.datetime.utcnow()
        params['ClientToken'] = module.params.get('client_token')

    policy = None
    if module.params.get('policy'):
        try:
            policy = json.loads(module.params.get('policy'))
        except ValueError as e:
            module.fail_json(msg=str(e), exception=traceback.format_exc(),
                             **camel_dict_to_snake_dict(e.response))

    elif module.params.get('policy_file'):
        try:
            with open(module.params.get('policy_file'), 'r') as json_data:
                policy = json.load(json_data)
        except Exception as e:
            module.fail_json(msg=str(e), exception=traceback.format_exc(),
                             **camel_dict_to_snake_dict(e.response))

    if policy:
        params['PolicyDocument'] = json.dumps(policy)

    try:
        changed = True
        result = camel_dict_to_snake_dict(client.create_vpc_endpoint(**params)['VpcEndpoint'])
        if token_provided and (request_time > result['creation_timestamp'].replace(tzinfo=None)):
            changed = False
        elif module.params.get('wait') and not module.check_mode:
            status_achieved, result = wait_for_status(client, module, result['vpc_endpoint_id'], 'available')
            if not status_achieved:
                module.fail_json(msg='Error waiting for vpc endpoint to become available - please check the AWS console')
    except botocore.exceptions.ClientError as e:
        if "DryRunOperation" in e.message:
            changed = True
            result = 'Would have created VPC Endpoint if not in check mode'
        elif "IdempotentParameterMismatch" in e.message:
            module.fail_json(msg="IdempotentParameterMismatch - updates of endpoints are not allowed by the API")
        elif "RouteAlreadyExists" in e.message:
            module.fail_json(msg="RouteAlreadyExists for one of the route tables - update is not allowed by the API")
        else:
            module.fail_json(msg=str(e), exception=traceback.format_exc(),
                             **camel_dict_to_snake_dict(e.response))
    except Exception as e:
        module.fail_json(msg=str(e), exception=traceback.format_exc(),
                         **camel_dict_to_snake_dict(e.response))

    return changed, result
Example #2
0
def get_trail_facts(module, client, name):
    """
    Describes existing trail in an account

    module : AnsibleModule object
    client : boto3 client connection object
    name : Name of the trail
    """
    # get Trail info
    try:
        trail_resp = client.describe_trails(trailNameList=[name])
    except ClientError as err:
        module.fail_json(msg=err.message, exception=traceback.format_exc(), **camel_dict_to_snake_dict(err.response))

    # Now check to see if our trail exists and get status and tags
    if len(trail_resp['trailList']):
        trail = trail_resp['trailList'][0]
        try:
            status_resp = client.get_trail_status(Name=trail['Name'])
            tags_list = client.list_tags(ResourceIdList=[trail['TrailARN']])
        except ClientError as err:
            module.fail_json(msg=err.message, exception=traceback.format_exc(), **camel_dict_to_snake_dict(err.response))

        trail['IsLogging'] = status_resp['IsLogging']
        trail['tags'] = boto3_tag_list_to_ansible_dict(tags_list['ResourceTagList'][0]['TagsList'])
        # Check for non-existent values and populate with None
        optional_vals = set(['S3KeyPrefix', 'SnsTopicName', 'SnsTopicARN', 'CloudWatchLogsLogGroupArn', 'CloudWatchLogsRoleArn', 'KmsKeyId'])
        for v in optional_vals - set(trail.keys()):
            trail[v] = None
        return trail

    else:
        # trail doesn't exist return None
        return None
Example #3
0
def find_clusters(conn, module, identifier=None, tags=None):

    try:
        cluster_paginator = conn.get_paginator('describe_clusters')
        clusters = cluster_paginator.paginate().build_full_result()
    except ClientError as e:
        module.fail_json(msg=e.message,
                         exception=traceback.format_exc(),
                         **camel_dict_to_snake_dict(e.response))

    matched_clusters = []

    if identifier is not None:
        identifier_prog = re.compile('^' + identifier)

    for cluster in clusters['Clusters']:

        matched_identifier = True
        if identifier:
            matched_identifier = identifier_prog.search(
                cluster['ClusterIdentifier'])

        matched_tags = True
        if tags:
            matched_tags = match_tags(tags, cluster)

        if matched_identifier and matched_tags:
            matched_clusters.append(camel_dict_to_snake_dict(cluster))

    return matched_clusters
Example #4
0
def describe_subnets(connection, module):
    """
    Describe Subnets.

    module  : AnsibleModule object
    connection  : boto3 client connection object
    """
    # collect parameters
    filters = ansible_dict_to_boto3_filter_list(module.params.get('filters'))
    subnet_ids = module.params.get('subnet_ids')

    if subnet_ids is None:
        # Set subnet_ids to empty list if it is None
        subnet_ids = []

    # init empty list for return vars
    subnet_info = list()

    # Get the basic VPC info
    try:
        response = describe_subnets_with_backoff(connection, subnet_ids, filters)
    except botocore.exceptions.ClientError as e:
        module.fail_json(msg=to_native(e), exception=traceback.format_exc(), **camel_dict_to_snake_dict(e.response))

    for subnet in response['Subnets']:
        # for backwards compatibility
        subnet['id'] = subnet['SubnetId']
        subnet_info.append(camel_dict_to_snake_dict(subnet))
        # convert tag list to ansible dict
        subnet_info[-1]['tags'] = boto3_tag_list_to_ansible_dict(subnet.get('Tags', []))

    module.exit_json(subnets=subnet_info)
Example #5
0
def update_tags(module, connection, group, tags):
    changed = False
    existing_tags = connection.list_tags_for_resource(
        ResourceName=group['DBParameterGroupArn'])['TagList']
    to_update, to_delete = compare_aws_tags(
        boto3_tag_list_to_ansible_dict(existing_tags), tags,
        module.params['purge_tags'])
    if to_update:
        try:
            connection.add_tags_to_resource(
                ResourceName=group['DBParameterGroupArn'],
                Tags=ansible_dict_to_boto3_tag_list(to_update))
            changed = True
        except botocore.exceptions.ClientError as e:
            module.fail_json(msg="Couldn't add tags to parameter group: %s" %
                             str(e),
                             exception=traceback.format_exc(),
                             **camel_dict_to_snake_dict(e.response))
        except botocore.exceptions.ParamValidationError as e:
            # Usually a tag value has been passed as an int or bool, needs to be a string
            # The AWS exception message is reasonably ok for this purpose
            module.fail_json(msg="Couldn't add tags to parameter group: %s." %
                             str(e),
                             exception=traceback.format_exc())
    if to_delete:
        try:
            connection.remove_tags_from_resource(
                ResourceName=group['DBParameterGroupArn'], TagKeys=to_delete)
            changed = True
        except botocore.exceptions.ClientError as e:
            module.fail_json(
                msg="Couldn't remove tags from parameter group: %s" % str(e),
                exception=traceback.format_exc(),
                **camel_dict_to_snake_dict(e.response))
    return changed
Example #6
0
def list_ec2_instances(connection, module):

    instance_ids = module.params.get("instance_ids")
    filters = ansible_dict_to_boto3_filter_list(module.params.get("filters"))

    try:
        reservations_paginator = connection.get_paginator('describe_instances')
        reservations = reservations_paginator.paginate(
            InstanceIds=instance_ids, Filters=filters).build_full_result()
    except ClientError as e:
        module.fail_json(msg=e.message,
                         exception=traceback.format_exc(),
                         **camel_dict_to_snake_dict(e.response))

    # Get instances from reservations
    instances = []
    for reservation in reservations['Reservations']:
        instances = instances + reservation['Instances']

    # Turn the boto3 result in to ansible_friendly_snaked_names
    snaked_instances = [
        camel_dict_to_snake_dict(instance) for instance in instances
    ]

    # Turn the boto3 result in to ansible friendly tag dictionary
    for instance in snaked_instances:
        instance['tags'] = boto3_tag_list_to_ansible_dict(
            instance.get('tags', []), 'key', 'value')

    module.exit_json(instances=snaked_instances)
def get_subnet_info(subnet):
    if 'Subnets' in subnet:
        return [get_subnet_info(s) for s in subnet['Subnets']]
    elif 'Subnet' in subnet:
        subnet = camel_dict_to_snake_dict(subnet['Subnet'])
    else:
        subnet = camel_dict_to_snake_dict(subnet)

    if 'tags' in subnet:
        subnet['tags'] = boto3_tag_list_to_ansible_dict(subnet['tags'])
    else:
        subnet['tags'] = dict()

    if 'subnet_id' in subnet:
        subnet['id'] = subnet['subnet_id']
        del subnet['subnet_id']

    subnet['ipv6_cidr_block'] = ''
    subnet['ipv6_association_id'] = ''
    ipv6set = subnet.get('ipv6_cidr_block_association_set')
    if ipv6set:
        for item in ipv6set:
            if item.get('ipv6_cidr_block_state',
                        {}).get('state') in ('associated', 'associating'):
                subnet['ipv6_cidr_block'] = item['ipv6_cidr_block']
                subnet['ipv6_association_id'] = item['association_id']

    return subnet
Example #8
0
def create_instance(module, client, instance_name):

    inst = find_instance_info(module, client, instance_name)
    if inst:
        module.exit_json(changed=False, instance=camel_dict_to_snake_dict(inst))
    else:
        create_params = {'instanceNames': [instance_name],
                         'availabilityZone': module.params.get('zone'),
                         'blueprintId': module.params.get('blueprint_id'),
                         'bundleId': module.params.get('bundle_id'),
                         'userData': module.params.get('user_data')}

        key_pair_name = module.params.get('key_pair_name')
        if key_pair_name:
            create_params['keyPairName'] = key_pair_name

        try:
            client.create_instances(**create_params)
        except botocore.exceptions.ClientError as e:
            module.fail_json_aws(e)

        wait = module.params.get('wait')
        if wait:
            desired_states = ['running']
            wait_for_instance_state(module, client, instance_name, desired_states)
        inst = find_instance_info(module, client, instance_name, fail_if_not_found=True)

        module.exit_json(changed=True, instance=camel_dict_to_snake_dict(inst))
def main():
    argument_spec = ec2_argument_spec()
    argument_spec.update(
        dict(
            vpc_id=dict(),
            service=dict(),
            policy=dict(type='json'),
            policy_file=dict(type='path', aliases=['policy_path']),
            state=dict(default='present', choices=['present', 'absent']),
            wait=dict(type='bool', default=False),
            wait_timeout=dict(type='int', default=320, required=False),
            route_table_ids=dict(type='list'),
            vpc_endpoint_id=dict(),
            client_token=dict(),
        )
    )
    module = AnsibleModule(
        argument_spec=argument_spec,
        supports_check_mode=True,
        mutually_exclusive=[['policy', 'policy_file']],
        required_if=[
            ['state', 'present', ['vpc_id', 'service']],
            ['state', 'absent', ['vpc_endpoint_id']],
        ]
    )

    # Validate Requirements
    if not HAS_BOTO3:
        module.fail_json(msg='botocore and boto3 are required for this module')

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

    try:
        region, ec2_url, aws_connect_kwargs = get_aws_connection_info(module, boto3=True)
    except NameError as e:
        # Getting around the get_aws_connection_info boto reliance for region
        if "global name 'boto' is not defined" in e.message:
            module.params['region'] = botocore.session.get_session().get_config_variable('region')
            if not module.params['region']:
                module.fail_json(msg="Error - no region provided")
        else:
            module.fail_json(msg="Can't retrieve connection information - " + str(e),
                             exception=traceback.format_exc(),
                             **camel_dict_to_snake_dict(e.response))

    try:
        region, ec2_url, aws_connect_kwargs = get_aws_connection_info(module, boto3=True)
        ec2 = boto3_conn(module, conn_type='client', resource='ec2', region=region, endpoint=ec2_url, **aws_connect_kwargs)
    except botocore.exceptions.NoCredentialsError as e:
        module.fail_json(msg="Failed to connect to AWS due to wrong or missing credentials: %s" % str(e),
                         exception=traceback.format_exc(),
                         **camel_dict_to_snake_dict(e.response))

    # Ensure resource is present
    if state == 'present':
        (changed, results) = setup_creation(ec2, module)
    else:
        (changed, results) = setup_removal(ec2, module)

    module.exit_json(changed=changed, result=results)
Example #10
0
def ensure_present(module, connection):
    groupname = module.params['name']
    tags = module.params.get('tags')
    changed = False
    errors = []
    try:
        response = connection.describe_db_parameter_groups(
            DBParameterGroupName=groupname)
    except botocore.exceptions.ClientError as e:
        if e.response['Error']['Code'] == 'DBParameterGroupNotFound':
            response = None
        else:
            module.fail_json(
                msg="Couldn't access parameter group information: %s" % str(e),
                exception=traceback.format_exc(),
                **camel_dict_to_snake_dict(e.response))
    if not response:
        params = dict(DBParameterGroupName=groupname,
                      DBParameterGroupFamily=module.params['engine'],
                      Description=module.params['description'])
        if tags:
            params['Tags'] = ansible_dict_to_boto3_tag_list(tags)
        try:
            response = connection.create_db_parameter_group(**params)
            changed = True
        except botocore.exceptions.ClientError as e:
            module.fail_json(msg="Couldn't create parameter group: %s" %
                             str(e),
                             exception=traceback.format_exc(),
                             **camel_dict_to_snake_dict(e.response))
    else:
        group = response['DBParameterGroups'][0]
        if tags:
            changed = update_tags(module, connection, group, tags)

    if module.params.get('params'):
        params_changed, errors = update_parameters(module, connection)
        changed = changed or params_changed

    try:
        response = connection.describe_db_parameter_groups(
            DBParameterGroupName=groupname)
        group = camel_dict_to_snake_dict(response['DBParameterGroups'][0])
    except botocore.exceptions.ClientError as e:
        module.fail_json(
            msg="Couldn't obtain parameter group information: %s" % str(e),
            exception=traceback.format_exc(),
            **camel_dict_to_snake_dict(e.response))
    try:
        tags = connection.list_tags_for_resource(
            ResourceName=group['db_parameter_group_arn'])['TagList']
    except botocore.exceptions.ClientError as e:
        module.fail_json(msg="Couldn't obtain parameter group tags: %s" %
                         str(e),
                         exception=traceback.format_exc(),
                         **camel_dict_to_snake_dict(e.response))
    group['tags'] = boto3_tag_list_to_ansible_dict(tags)

    module.exit_json(changed=changed, errors=errors, **group)
Example #11
0
def list_ec2_images(ec2_client, module):

    image_ids = module.params.get("image_ids")
    owners = module.params.get("owners")
    executable_users = module.params.get("executable_users")
    filters = module.params.get("filters")
    owner_param = []

    # describe_images is *very* slow if you pass the `Owners`
    # param (unless it's self), for some reason.
    # Converting the owners to filters and removing from the
    # owners param greatly speeds things up.
    # Implementation based on aioue's suggestion in #24886
    for owner in owners:
        if owner.isdigit():
            if 'owner-id' not in filters:
                filters['owner-id'] = list()
            filters['owner-id'].append(owner)
        elif owner == 'self':
            # self not a valid owner-alias filter (https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeImages.html)
            owner_param.append(owner)
        else:
            if 'owner-alias' not in filters:
                filters['owner-alias'] = list()
            filters['owner-alias'].append(owner)

    filters = ansible_dict_to_boto3_filter_list(filters)

    try:
        images = ec2_client.describe_images(ImageIds=image_ids,
                                            Filters=filters,
                                            Owners=owner_param,
                                            ExecutableUsers=executable_users)
        images = [
            camel_dict_to_snake_dict(image) for image in images["Images"]
        ]
    except (ClientError, BotoCoreError) as err:
        module.fail_json_aws(err, msg="error describing images")
    for image in images:
        try:
            image['tags'] = boto3_tag_list_to_ansible_dict(
                image.get('tags', []))
            if module.params.get("describe_image_attributes"):
                launch_permissions = ec2_client.describe_image_attribute(
                    Attribute='launchPermission',
                    ImageId=image['image_id'])['LaunchPermissions']
                image['launch_permissions'] = [
                    camel_dict_to_snake_dict(perm)
                    for perm in launch_permissions
                ]
        except (ClientError, BotoCoreError) as err:
            # describing launch permissions of images owned by others is not permitted, but shouldn't cause failures
            pass

    images.sort(
        key=lambda e: e.get('creation_date', '')
    )  # it may be possible that creation_date does not always exist
    module.exit_json(images=images)
Example #12
0
def list_target_groups(connection, module):

    load_balancer_arn = module.params.get("load_balancer_arn")
    target_group_arns = module.params.get("target_group_arns")
    names = module.params.get("names")
    collect_targets_health = module.params.get("collect_targets_health")

    try:
        target_group_paginator = connection.get_paginator(
            'describe_target_groups')
        if not load_balancer_arn and not target_group_arns and not names:
            target_groups = target_group_paginator.paginate(
            ).build_full_result()
        if load_balancer_arn:
            target_groups = target_group_paginator.paginate(
                LoadBalancerArn=load_balancer_arn).build_full_result()
        if target_group_arns:
            target_groups = target_group_paginator.paginate(
                TargetGroupArns=target_group_arns).build_full_result()
        if names:
            target_groups = target_group_paginator.paginate(
                Names=names).build_full_result()
    except ClientError as e:
        if e.response['Error']['Code'] == 'TargetGroupNotFound':
            module.exit_json(target_groups=[])
        else:
            module.fail_json(msg=e.message,
                             exception=traceback.format_exc(),
                             **camel_dict_to_snake_dict(e.response))
    except NoCredentialsError as e:
        module.fail_json(msg="AWS authentication problem. " + e.message,
                         exception=traceback.format_exc())

    # Get the attributes and tags for each target group
    for target_group in target_groups['TargetGroups']:
        target_group.update(
            get_target_group_attributes(connection, module,
                                        target_group['TargetGroupArn']))

    # Turn the boto3 result in to ansible_friendly_snaked_names
    snaked_target_groups = [
        camel_dict_to_snake_dict(target_group)
        for target_group in target_groups['TargetGroups']
    ]

    # Get tags for each target group
    for snaked_target_group in snaked_target_groups:
        snaked_target_group['tags'] = get_target_group_tags(
            connection, module, snaked_target_group['target_group_arn'])
        if collect_targets_health:
            snaked_target_group['targets_health_description'] = [
                camel_dict_to_snake_dict(target)
                for target in get_target_group_targets_health(
                    connection, module,
                    snaked_target_group['target_group_arn'])
            ]

    module.exit_json(target_groups=snaked_target_groups)
def list_load_balancers(connection, module):

    load_balancer_arns = module.params.get("load_balancer_arns")
    names = module.params.get("names")

    try:
        load_balancer_paginator = connection.get_paginator(
            'describe_load_balancers')
        if not load_balancer_arns and not names:
            load_balancers = load_balancer_paginator.paginate(
            ).build_full_result()
        if load_balancer_arns:
            load_balancers = load_balancer_paginator.paginate(
                LoadBalancerArns=load_balancer_arns).build_full_result()
        if names:
            load_balancers = load_balancer_paginator.paginate(
                Names=names).build_full_result()
    except ClientError as e:
        if e.response['Error']['Code'] == 'LoadBalancerNotFound':
            module.exit_json(load_balancers=[])
        else:
            module.fail_json(msg=e.message,
                             exception=traceback.format_exc(),
                             **camel_dict_to_snake_dict(e.response))
    except NoCredentialsError as e:
        module.fail_json(msg="AWS authentication problem. " + e.message,
                         exception=traceback.format_exc())

    for load_balancer in load_balancers['LoadBalancers']:
        # Get the attributes for each elb
        load_balancer.update(
            get_load_balancer_attributes(connection, module,
                                         load_balancer['LoadBalancerArn']))

        # Get the listeners for each elb
        load_balancer['listeners'] = get_elb_listeners(
            connection, module, load_balancer['LoadBalancerArn'])

        # For each listener, get listener rules
        for listener in load_balancer['listeners']:
            listener['rules'] = get_listener_rules(connection, module,
                                                   listener['ListenerArn'])

    # Turn the boto3 result in to ansible_friendly_snaked_names
    snaked_load_balancers = [
        camel_dict_to_snake_dict(load_balancer)
        for load_balancer in load_balancers['LoadBalancers']
    ]

    # Get tags for each load balancer
    for snaked_load_balancer in snaked_load_balancers:
        snaked_load_balancer['tags'] = get_load_balancer_tags(
            connection, module, snaked_load_balancer['load_balancer_arn'])

    module.exit_json(load_balancers=snaked_load_balancers)
def ensure_present(client, module):
    name = module.params.get('name')
    subnets = module.params['subnets']
    groups = module.params['security_groups']
    wait = module.params.get('wait')
    cluster = get_cluster(client, module)
    try:
        ec2 = module.client('ec2')
        vpc_id = ec2.describe_subnets(SubnetIds=[subnets[0]])['Subnets'][0]['VpcId']
        groups = get_ec2_security_group_ids_from_names(groups, ec2, vpc_id)
    except (botocore.exceptions.BotoCoreError, botocore.exceptions.ClientError) as e:
        module.fail_json_aws(e, msg="Couldn't lookup security groups")

    if cluster:
        if set(cluster['resourcesVpcConfig']['subnetIds']) != set(subnets):
            module.fail_json(msg="Cannot modify subnets of existing cluster")
        if set(cluster['resourcesVpcConfig']['securityGroupIds']) != set(groups):
            module.fail_json(msg="Cannot modify security groups of existing cluster")
        if module.params.get('version') and module.params.get('version') != cluster['version']:
            module.fail_json(msg="Cannot modify version of existing cluster")

        if wait:
            wait_until(client, module, 'cluster_active')
            # Ensure that fields that are only available for active clusters are
            # included in the returned value
            cluster = get_cluster(client, module)

        module.exit_json(changed=False, **camel_dict_to_snake_dict(cluster))

    if module.check_mode:
        module.exit_json(changed=True)
    try:
        params = dict(name=name,
                      roleArn=module.params['role_arn'],
                      resourcesVpcConfig=dict(
                          subnetIds=subnets,
                          securityGroupIds=groups),
                      clientRequestToken='ansible-create-%s' % name)
        if module.params['version']:
            params['version'] = module.params['version']
        cluster = client.create_cluster(**params)['cluster']
    except botocore.exceptions.EndpointConnectionError as e:
        module.fail_json(msg="Region %s is not supported by EKS" % client.meta.region_name)
    except (botocore.exceptions.BotoCoreError, botocore.exceptions.ClientError) as e:
        module.fail_json_aws(e, msg="Couldn't create cluster %s" % name)

    if wait:
        wait_until(client, module, 'cluster_active')
        # Ensure that fields that are only available for active clusters are
        # included in the returned value
        cluster = get_cluster(client, module)

    module.exit_json(changed=True, **camel_dict_to_snake_dict(cluster))
def get_bucket_list(module, connection):
    """
    Return result of list_buckets json encoded
    :param module:
    :param connection:
    :return:
    """
    try:
        buckets = camel_dict_to_snake_dict(connection.list_buckets())['buckets']
    except botocore.exceptions.ClientError as e:
        module.fail_json(msg=to_native(e), exception=traceback.format_exc(), **camel_dict_to_snake_dict(e.response))

    return buckets
def list_mfa_devices(connection, module):
    user_name = module.params.get('user_name')
    changed = False

    args = {}
    if user_name is not None:
        args['UserName'] = user_name
    try:
        response = connection.list_mfa_devices(**args)
    except ClientError as e:
        module.fail_json(msg=e.message, **camel_dict_to_snake_dict(e.response))

    module.exit_json(changed=changed, **camel_dict_to_snake_dict(response))
Example #17
0
def main():
    argument_spec = dict(state=dict(required=True,
                                    choices=['present', 'absent']),
                         name=dict(),
                         location=dict(),
                         bandwidth=dict(choices=['1Gbps', '10Gbps']),
                         link_aggregation_group=dict(),
                         connection_id=dict(),
                         forced_update=dict(type='bool', default=False))

    module = AnsibleAWSModule(argument_spec=argument_spec,
                              required_one_of=[('connection_id', 'name')],
                              required_if=[('state', 'present',
                                            ('location', 'bandwidth'))])

    connection = module.client('directconnect')

    state = module.params.get('state')
    try:
        connection_id = connection_exists(
            connection,
            connection_id=module.params.get('connection_id'),
            connection_name=module.params.get('name'))
        if not connection_id and module.params.get('connection_id'):
            module.fail_json(
                msg="The Direct Connect connection {0} does not exist.".format(
                    module.params.get('connection_id')))

        if state == 'present':
            changed, connection_id = ensure_present(
                connection,
                connection_id=connection_id,
                connection_name=module.params.get('name'),
                location=module.params.get('location'),
                bandwidth=module.params.get('bandwidth'),
                lag_id=module.params.get('link_aggregation_group'),
                forced_update=module.params.get('forced_update'))
            response = connection_status(connection, connection_id)
        elif state == 'absent':
            changed = ensure_absent(connection, connection_id)
            response = {}
    except DirectConnectError as e:
        if e.last_traceback:
            module.fail_json(msg=e.msg,
                             exception=e.last_traceback,
                             **camel_dict_to_snake_dict(e.exception.response))
        else:
            module.fail_json(msg=e.msg)

    module.exit_json(changed=changed, **camel_dict_to_snake_dict(response))
def get_or_create_policy_version(module, iam, policy, policy_document):
    try:
        versions = iam.list_policy_versions(
            PolicyArn=policy['Arn'])['Versions']
    except botocore.exceptions.ClientError as e:
        module.fail_json(msg="Couldn't list policy versions: %s" % str(e),
                         exception=traceback.format_exc(),
                         **camel_dict_to_snake_dict(e.response))
    for v in versions:
        try:
            document = iam.get_policy_version(
                PolicyArn=policy['Arn'],
                VersionId=v['VersionId'])['PolicyVersion']['Document']
        except botocore.exceptions.ClientError as e:
            module.fail_json(msg="Couldn't get policy version %s: %s" %
                             (v['VersionId'], str(e)),
                             exception=traceback.format_exc(),
                             **camel_dict_to_snake_dict(e.response))
        # If the current policy matches the existing one
        if not compare_policies(document, json.loads(
                to_native(policy_document))):
            return v, False

    # No existing version so create one
    # There is a service limit (typically 5) of policy versions.
    #
    # Rather than assume that it is 5, we'll try to create the policy
    # and if that doesn't work, delete the oldest non default policy version
    # and try again.
    try:
        version = iam.create_policy_version(
            PolicyArn=policy['Arn'],
            PolicyDocument=policy_document)['PolicyVersion']
        return version, True
    except botocore.exceptions.ClientError as e:
        if e.response['Error']['Code'] == 'LimitExceeded':
            delete_oldest_non_default_version(module, iam, policy)
            try:
                version = iam.create_policy_version(
                    PolicyArn=policy['Arn'],
                    PolicyDocument=policy_document)['PolicyVersion']
                return version, True
            except botocore.exceptions.ClientError as second_e:
                e = second_e
        # Handle both when the exception isn't LimitExceeded or
        # the second attempt still failed
        module.fail_json(msg="Couldn't create policy version: %s" % str(e),
                         exception=traceback.format_exc(),
                         **camel_dict_to_snake_dict(e.response))
def main():
    argument_spec = ec2_argument_spec()
    argument_spec.update(dict(filters=dict(default={}, type='dict')))

    module = AnsibleModule(argument_spec=argument_spec)
    if module._name == 'aws_acm_facts':
        module.deprecate(
            "The 'aws_az_facts' module has been renamed to 'aws_az_info'",
            version='2.13')

    if not HAS_BOTO3:
        module.fail_json(msg='boto3 required for this module')

    region, ec2_url, aws_connect_params = get_aws_connection_info(module,
                                                                  boto3=True)
    connection = boto3_conn(module,
                            conn_type='client',
                            resource='ec2',
                            region=region,
                            endpoint=ec2_url,
                            **aws_connect_params)

    # Replace filter key underscores with dashes, for compatibility
    sanitized_filters = dict((k.replace('_', '-'), v)
                             for k, v in module.params.get('filters').items())

    try:
        availability_zones = connection.describe_availability_zones(
            Filters=ansible_dict_to_boto3_filter_list(sanitized_filters))
    except ClientError as e:
        module.fail_json(
            msg="Unable to describe availability zones: {0}".format(
                to_native(e)),
            exception=traceback.format_exc(),
            **camel_dict_to_snake_dict(e.response))
    except BotoCoreError as e:
        module.fail_json(
            msg="Unable to describe availability zones: {0}".format(
                to_native(e)),
            exception=traceback.format_exc())

    # Turn the boto3 result into ansible_friendly_snaked_names
    snaked_availability_zones = [
        camel_dict_to_snake_dict(az)
        for az in availability_zones['AvailabilityZones']
    ]

    module.exit_json(availability_zones=snaked_availability_zones)
def main():
    """
    Main entry point.

    :return dict: ansible facts
    """
    argument_spec = ec2_argument_spec()
    argument_spec.update(
        dict(
            state=dict(required=False, default='present', choices=['present', 'absent']),
            function_name=dict(required=True),
            name=dict(required=True, aliases=['alias_name']),
            function_version=dict(type='int', required=False, default=0, aliases=['version']),
            description=dict(required=False, default=None),
        )
    )

    module = AnsibleModule(
        argument_spec=argument_spec,
        supports_check_mode=True,
        mutually_exclusive=[],
        required_together=[]
    )

    # validate dependencies
    if not HAS_BOTO3:
        module.fail_json(msg='boto3 is required for this module.')

    aws = AWSConnection(module, ['lambda'])

    validate_params(module, aws)

    results = lambda_alias(module, aws)

    module.exit_json(**camel_dict_to_snake_dict(results))
Example #21
0
def main():

    argument_spec = ec2_argument_spec()
    argument_spec.update(
        dict(
            name=dict(type='str'),
            tags=dict(type='dict'),
        )
    )
    module = AnsibleModule(argument_spec=argument_spec)
    if module._name == 'ec2_asg_facts':
        module.deprecate("The 'ec2_asg_facts' module has been renamed to 'ec2_asg_info'", version='2.13')

    if not HAS_BOTO3:
        module.fail_json(msg='boto3 required for this module')

    asg_name = module.params.get('name')
    asg_tags = module.params.get('tags')

    try:
        region, ec2_url, aws_connect_kwargs = get_aws_connection_info(module, boto3=True)
        autoscaling = boto3_conn(module, conn_type='client', resource='autoscaling', region=region, endpoint=ec2_url, **aws_connect_kwargs)
    except ClientError as e:
        module.fail_json(msg=e.message, **camel_dict_to_snake_dict(e.response))

    results = find_asgs(autoscaling, module, name=asg_name, tags=asg_tags)
    module.exit_json(results=results)
Example #22
0
    def _refresh_data(self, cache_cluster_data=None):
        """Refresh data about this cache cluster"""

        if cache_cluster_data is None:
            try:
                response = self.conn.describe_cache_clusters(
                    CacheClusterId=self.name, ShowCacheNodeInfo=True)
            except botocore.exceptions.ClientError as e:
                if e.response['Error']['Code'] == 'CacheClusterNotFound':
                    self.data = None
                    self.status = 'gone'
                    return
                else:
                    self.module.fail_json(msg=e.message,
                                          exception=format_exc(),
                                          **camel_dict_to_snake_dict(
                                              e.response))
            cache_cluster_data = response['CacheClusters'][0]
        self.data = cache_cluster_data
        self.status = self.data['CacheClusterStatus']

        # The documentation for elasticache lies -- status on rebooting is set
        # to 'rebooting cache cluster nodes' instead of 'rebooting'. Fix it
        # here to make status checks etc. more sane.
        if self.status == 'rebooting cache cluster nodes':
            self.status = 'rebooting'
Example #23
0
    def reboot(self):
        """Reboot the cache cluster"""
        if not self.exists():
            msg = "'%s' is %s. Cannot reboot."
            self.module.fail_json(msg=msg % (self.name, self.status))
        if self.status == 'rebooting':
            return
        if self.status in ['creating', 'modifying']:
            if self.wait:
                self._wait_for_status('available')
            else:
                msg = "'%s' is currently %s. Cannot reboot."
                self.module.fail_json(msg=msg % (self.name, self.status))

        # Collect ALL nodes for reboot
        cache_node_ids = [cn['CacheNodeId'] for cn in self.data['CacheNodes']]
        try:
            self.conn.reboot_cache_cluster(CacheClusterId=self.name,
                                           CacheNodeIdsToReboot=cache_node_ids)
        except botocore.exceptions.ClientError as e:
            self.module.fail_json(msg=e.message,
                                  exception=format_exc(),
                                  **camel_dict_to_snake_dict(e.response))

        self._refresh_data()

        self.changed = True
        if self.wait:
            self._wait_for_status('available')
Example #24
0
def get_result(client, dp_id):
    """ Get the current state of the data pipeline and reformat it to snake_case for exit_json

    :param object client: boto3 datapipeline client
    :param string dp_id: pipeline id
    :returns: reformatted dict of pipeline description

     """
    # pipeline_description returns a pipelineDescriptionList of length 1
    # dp is a dict with keys "description" (str), "fields" (list), "name" (str), "pipelineId" (str), "tags" (dict)
    dp = pipeline_description(client, dp_id)['pipelineDescriptionList'][0]

    # Get uniqueId and pipelineState in fields to add to the exit_json result
    dp["unique_id"] = pipeline_field(client, dp_id, field="uniqueId")
    dp["pipeline_state"] = pipeline_field(client,
                                          dp_id,
                                          field="@pipelineState")

    # Remove fields; can't make a list snake_case and most of the data is redundant
    del dp["fields"]

    # Note: tags is already formatted fine so we don't need to do anything with it

    # Reformat data pipeline and add reformatted fields back
    dp = camel_dict_to_snake_dict(dp)
    return dp
def main():
    argument_spec = ec2_argument_spec()
    argument_spec.update(dict(task_definition=dict(required=True, type='str')))

    module = AnsibleAWSModule(argument_spec=argument_spec,
                              supports_check_mode=True)
    if module._name == 'ecs_taskdefinition_facts':
        module.deprecate(
            "The 'ecs_taskdefinition_facts' module has been renamed to 'ecs_taskdefinition_info'",
            version='2.13')

    region, ec2_url, aws_connect_kwargs = get_aws_connection_info(module,
                                                                  boto3=True)
    ecs = boto3_conn(module,
                     conn_type='client',
                     resource='ecs',
                     region=region,
                     endpoint=ec2_url,
                     **aws_connect_kwargs)

    try:
        ecs_td = ecs.describe_task_definition(
            taskDefinition=module.params['task_definition'])['taskDefinition']
    except botocore.exceptions.ClientError:
        ecs_td = {}

    module.exit_json(changed=False, **camel_dict_to_snake_dict(ecs_td))
Example #26
0
def instance_info(module, conn):
    instance_name = module.params.get('db_instance_identifier')
    filters = module.params.get('filters')

    params = dict()
    if instance_name:
        params['DBInstanceIdentifier'] = instance_name
    if filters:
        params['Filters'] = ansible_dict_to_boto3_filter_list(filters)

    paginator = conn.get_paginator('describe_db_instances')
    try:
        results = paginator.paginate(**params).build_full_result()['DBInstances']
    except is_boto3_error_code('DBInstanceNotFound'):
        results = []
    except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e:  # pylint: disable=duplicate-except
        module.fail_json_aws(e, "Couldn't get instance information")

    for instance in results:
        try:
            instance['Tags'] = boto3_tag_list_to_ansible_dict(conn.list_tags_for_resource(ResourceName=instance['DBInstanceArn'],
                                                                                          aws_retry=True)['TagList'])
        except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e:
            module.fail_json_aws(e, "Couldn't get tags for instance %s" % instance['DBInstanceIdentifier'])

    return dict(changed=False, instances=[camel_dict_to_snake_dict(instance, ignore_list=['Tags']) for instance in results])
Example #27
0
def list_launch_configs(connection, module):

    launch_config_name = module.params.get("name")
    sort = module.params.get('sort')
    sort_order = module.params.get('sort_order')
    sort_start = module.params.get('sort_start')
    sort_end = module.params.get('sort_end')

    try:
        pg = connection.get_paginator('describe_launch_configurations')
        launch_configs = pg.paginate(
            LaunchConfigurationNames=launch_config_name).build_full_result()
    except ClientError as e:
        module.fail_json(msg=e.message)

    snaked_launch_configs = []
    for launch_config in launch_configs['LaunchConfigurations']:
        snaked_launch_configs.append(camel_dict_to_snake_dict(launch_config))

    for launch_config in snaked_launch_configs:
        if 'CreatedTime' in launch_config:
            launch_config['CreatedTime'] = str(launch_config['CreatedTime'])

    if sort:
        snaked_launch_configs.sort(key=lambda e: e[sort],
                                   reverse=(sort_order == 'descending'))

    if sort and sort_start and sort_end:
        snaked_launch_configs = snaked_launch_configs[sort_start:sort_end]
    elif sort and sort_start:
        snaked_launch_configs = snaked_launch_configs[sort_start:]
    elif sort and sort_end:
        snaked_launch_configs = snaked_launch_configs[:sort_end]

    module.exit_json(launch_configurations=snaked_launch_configs)
Example #28
0
def main():
    argument_spec = ec2_argument_spec()
    argument_spec.update(dict(
        subnet_ids=dict(type='list', default=[], aliases=['subnet_id']),
        filters=dict(type='dict', default={})
    ))

    module = AnsibleModule(argument_spec=argument_spec,
                           supports_check_mode=True)
    if module._name == 'ec2_vpc_subnet_facts':
        module.deprecate("The 'ec2_vpc_subnet_facts' module has been renamed to 'ec2_vpc_subnet_info'", version='2.13')

    if not HAS_BOTO3:
        module.fail_json(msg='boto3 is required for this module')

    region, ec2_url, aws_connect_params = get_aws_connection_info(module, boto3=True)

    if region:
        try:
            connection = boto3_conn(module, conn_type='client', resource='ec2', region=region, endpoint=ec2_url, **aws_connect_params)
        except (botocore.exceptions.NoCredentialsError, botocore.exceptions.ProfileNotFound) as e:
            module.fail_json(msg=to_native(e), exception=traceback.format_exc(), **camel_dict_to_snake_dict(e.response))
    else:
        module.fail_json(msg="Region must be specified")

    describe_subnets(connection, module)
def common_snapshot_info(module, conn, method, prefix, params):
    paginator = conn.get_paginator(method)
    try:
        results = paginator.paginate(**params).build_full_result()['%ss' %
                                                                   prefix]
    except is_boto3_error_code('%sNotFound' % prefix):
        results = []
    except (botocore.exceptions.ClientError,
            botocore.exceptions.BotoCoreError) as e:  # pylint: disable=duplicate-except
        module.fail_json_aws(e, "trying to get snapshot information")

    for snapshot in results:
        try:
            snapshot['Tags'] = boto3_tag_list_to_ansible_dict(
                conn.list_tags_for_resource(ResourceName=snapshot['%sArn' %
                                                                  prefix],
                                            aws_retry=True)['TagList'])
        except (botocore.exceptions.ClientError,
                botocore.exceptions.BotoCoreError) as e:
            module.fail_json_aws(
                e, "Couldn't get tags for snapshot %s" %
                snapshot['%sIdentifier' % prefix])

    return [
        camel_dict_to_snake_dict(snapshot, ignore_list=['Tags'])
        for snapshot in results
    ]
Example #30
0
    def delete(self):
        """Destroy an ElastiCache cluster"""
        if self.status == 'gone':
            return
        if self.status == 'deleting':
            if self.wait:
                self._wait_for_status('gone')
            return
        if self.status in ['creating', 'rebooting', 'modifying']:
            if self.wait:
                self._wait_for_status('available')
            else:
                msg = "'%s' is currently %s. Cannot delete."
                self.module.fail_json(msg=msg % (self.name, self.status))

        try:
            response = self.conn.delete_cache_cluster(CacheClusterId=self.name)
        except botocore.exceptions.ClientError as e:
            self.module.fail_json(msg=e.message,
                                  exception=format_exc(),
                                  **camel_dict_to_snake_dict(e.response))

        cache_cluster_data = response['CacheCluster']
        self._refresh_data(cache_cluster_data)

        self.changed = True
        if self.wait:
            self._wait_for_status('gone')