Example #1
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))
Example #2
0
    def get_info(self):
        info = {
            'name': self.name,
            'state': self.state,
            'subscriptions_new': self.subscriptions,
            'subscriptions_existing': self.subscriptions_existing,
            'subscriptions_deleted': self.subscriptions_deleted,
            'subscriptions_added': self.subscriptions_added,
            'subscriptions_purge': self.purge_subscriptions,
            'check_mode': self.check_mode,
            'topic_created': self.topic_created,
            'topic_deleted': self.topic_deleted,
            'attributes_set': self.attributes_set,
        }
        if self.state != 'absent':
            if self.topic_arn in self._list_topics():
                info.update(
                    camel_dict_to_snake_dict(
                        self.connection.get_topic_attributes(
                            TopicArn=self.topic_arn)['Attributes']))
                info['delivery_policy'] = info.pop('effective_delivery_policy')
            info['subscriptions'] = [
                camel_dict_to_snake_dict(sub)
                for sub in self._list_topic_subscriptions()
            ]

        return info
def set_logging(module, client, name, action):
    """
    Starts or stops logging based on given state

    module : AnsibleModule object
    client : boto3 client connection object
    name : The name or ARN of the CloudTrail to operate on
    action : start or stop
    """
    if action == 'start':
        try:
            client.start_logging(Name=name)
            return client.get_trail_status(Name=name)
        except ClientError as err:
            module.fail_json(msg=err.message,
                             exception=traceback.format_exc(),
                             **camel_dict_to_snake_dict(err.response))
    elif action == 'stop':
        try:
            client.stop_logging(Name=name)
            return client.get_trail_status(Name=name)
        except ClientError as err:
            module.fail_json(msg=err.message,
                             exception=traceback.format_exc(),
                             **camel_dict_to_snake_dict(err.response))
    else:
        module.fail_json(msg="Unsupported logging action")
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
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)
Example #6
0
def detach_all_entities(module, iam, policy, **kwargs):
    try:
        entities = iam.list_entities_for_policy(PolicyArn=policy['Arn'], **kwargs)
    except botocore.exceptions.ClientError as e:
        module.fail_json(msg="Couldn't detach list entities for policy %s: %s" % (policy['PolicyName'], str(e)),
                         exception=traceback.format_exc(),
                         **camel_dict_to_snake_dict(e.response))

    for g in entities['PolicyGroups']:
        try:
            iam.detach_group_policy(PolicyArn=policy['Arn'], GroupName=g['GroupName'])
        except botocore.exceptions.ClientError as e:
            module.fail_json(msg="Couldn't detach group policy %s: %s" % (g['GroupName'], str(e)),
                             exception=traceback.format_exc(),
                             **camel_dict_to_snake_dict(e.response))
    for u in entities['PolicyUsers']:
        try:
            iam.detach_user_policy(PolicyArn=policy['Arn'], UserName=u['UserName'])
        except botocore.exceptions.ClientError as e:
            module.fail_json(msg="Couldn't detach user policy %s: %s" % (u['UserName'], str(e)),
                             exception=traceback.format_exc(),
                             **camel_dict_to_snake_dict(e.response))
    for r in entities['PolicyRoles']:
        try:
            iam.detach_role_policy(PolicyArn=policy['Arn'], RoleName=r['RoleName'])
        except botocore.exceptions.ClientError as e:
            module.fail_json(msg="Couldn't detach role policy %s: %s" % (r['RoleName'], str(e)),
                             exception=traceback.format_exc(),
                             **camel_dict_to_snake_dict(e.response))
    if entities['IsTruncated']:
        detach_all_entities(module, iam, policy, marker=entities['Marker'])
Example #7
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
def setup_removal(client, module):
    params = dict()
    changed = False
    params['DryRun'] = module.check_mode
    if isinstance(module.params.get('vpc_endpoint_id'), string_types):
        params['VpcEndpointIds'] = [module.params.get('vpc_endpoint_id')]
    else:
        params['VpcEndpointIds'] = module.params.get('vpc_endpoint_id')
    try:
        result = client.delete_vpc_endpoints(**params)['Unsuccessful']
        if not module.check_mode and (result != []):
            module.fail_json(msg=result)
    except botocore.exceptions.ClientError as e:
        if "DryRunOperation" in e.message:
            changed = True
            result = 'Would have deleted VPC Endpoint if not in check mode'
        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 #9
0
def deregister_target(connection, module):

    """
    Deregisters a target to a target group

    :param module: ansible module object
    :param connection: boto3 connection
    :return:
    """

    deregister_unused = module.params.get("deregister_unused")
    target_group_arn = module.params.get("target_group_arn")
    target_id = module.params.get("target_id")
    target_port = module.params.get("target_port")
    target_status = module.params.get("target_status")
    target_status_timeout = module.params.get("target_status_timeout")
    changed = False

    if not target_group_arn:
        target_group_arn = convert_tg_name_to_arn(connection, module, module.params.get("target_group_name"))

    target = dict(Id=target_id)
    if target_port:
        target['Port'] = target_port

    target_description = describe_targets(connection, module, target_group_arn, target)
    current_target_state = target_description['TargetHealth']['State']
    current_target_reason = target_description['TargetHealth'].get('Reason')

    needs_deregister = False

    if deregister_unused and current_target_state == 'unused':
        if current_target_reason != 'Target.NotRegistered':
            needs_deregister = True
    elif current_target_state not in ['unused', 'draining']:
        needs_deregister = True

    if needs_deregister:
        try:
            deregister_target_with_backoff(connection, target_group_arn, target)
            changed = True
        except ClientError as e:
            module.fail_json(msg="Unable to deregister target {0}: {1}".format(target, to_native(e)),
                             exception=traceback.format_exc(), **camel_dict_to_snake_dict(e.response))
        except BotoCoreError as e:
            module.fail_json(msg="Unable to deregister target {0}: {1}".format(target, to_native(e)),
                             exception=traceback.format_exc())
    else:
        if current_target_reason != 'Target.NotRegistered' and current_target_state != 'draining':
            module.warn(warning="Your specified target has an 'unused' state but is still registered to the target group. " +
                                "To force deregistration use the 'deregister_unused' option.")

    if target_status:
        target_status_check(connection, module, target_group_arn, target, target_status, target_status_timeout)

    # Get all targets for the target group
    target_descriptions = describe_targets(connection, module, target_group_arn)

    module.exit_json(changed=changed, target_health_descriptions=camel_dict_to_snake_dict(target_descriptions), target_group_arn=target_group_arn)
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_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)
Example #13
0
def tag_trail(module, client, tags, trail_arn, curr_tags=None, dry_run=False):
    """
    Creates, updates, removes tags on a CloudTrail resource

    module : AnsibleModule object
    client : boto3 client connection object
    tags : Dict of tags converted from ansible_dict to boto3 list of dicts
    trail_arn : The ARN of the CloudTrail to operate on
    curr_tags : Dict of the current tags on resource, if any
    dry_run : true/false to determine if changes will be made if needed
    """
    adds = []
    removes = []
    updates = []
    changed = False

    if curr_tags is None:
        # No current tags so just convert all to a tag list
        adds = ansible_dict_to_boto3_tag_list(tags)
    else:
        curr_keys = set(curr_tags.keys())
        new_keys = set(tags.keys())
        add_keys = new_keys - curr_keys
        remove_keys = curr_keys - new_keys
        update_keys = dict()
        for k in curr_keys.intersection(new_keys):
            if curr_tags[k] != tags[k]:
                update_keys.update({k: tags[k]})

        adds = get_tag_list(add_keys, tags)
        removes = get_tag_list(remove_keys, curr_tags)
        updates = get_tag_list(update_keys, tags)

    if removes or updates:
        changed = True
        if not dry_run:
            try:
                client.remove_tags(ResourceId=trail_arn,
                                   TagsList=removes + updates)
            except ClientError as err:
                module.fail_json(msg=err.message,
                                 exception=traceback.format_exc(),
                                 **camel_dict_to_snake_dict(err.response))

    if updates or adds:
        changed = True
        if not dry_run:
            try:
                client.add_tags(ResourceId=trail_arn, TagsList=updates + adds)
            except ClientError as err:
                module.fail_json(msg=err.message,
                                 exception=traceback.format_exc(),
                                 **camel_dict_to_snake_dict(err.response))

    return changed
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 #15
0
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 ensure_ipv6_cidr_block(conn, module, subnet, ipv6_cidr, check_mode, start_time):
    wait = module.params['wait']
    changed = False

    if subnet['ipv6_association_id'] and not ipv6_cidr:
        if not check_mode:
            disassociate_ipv6_cidr(conn, module, subnet, start_time)
        changed = True

    if ipv6_cidr:
        filters = ansible_dict_to_boto3_filter_list({'ipv6-cidr-block-association.ipv6-cidr-block': ipv6_cidr,
                                                     'vpc-id': subnet['vpc_id']})

        try:
            check_subnets = get_subnet_info(describe_subnets_with_backoff(conn, Filters=filters))
        except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e:
            module.fail_json_aws(e, msg="Couldn't get subnet info")

        if check_subnets and check_subnets[0]['ipv6_cidr_block']:
            module.fail_json(msg="The IPv6 CIDR '{0}' conflicts with another subnet".format(ipv6_cidr))

        if subnet['ipv6_association_id']:
            if not check_mode:
                disassociate_ipv6_cidr(conn, module, subnet, start_time)
            changed = True

        try:
            if not check_mode:
                associate_resp = conn.associate_subnet_cidr_block(SubnetId=subnet['id'], Ipv6CidrBlock=ipv6_cidr)
            changed = True
        except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e:
            module.fail_json_aws(e, msg="Couldn't associate ipv6 cidr {0} to {1}".format(ipv6_cidr, subnet['id']))
        else:
            if not check_mode and wait:
                filters = ansible_dict_to_boto3_filter_list(
                    {'ipv6-cidr-block-association.state': ['associated'],
                     'vpc-id': subnet['vpc_id']}
                )
                handle_waiter(conn, module, 'subnet_exists',
                              {'SubnetIds': [subnet['id']], 'Filters': filters}, start_time)

        if associate_resp.get('Ipv6CidrBlockAssociation', {}).get('AssociationId'):
            subnet['ipv6_association_id'] = associate_resp['Ipv6CidrBlockAssociation']['AssociationId']
            subnet['ipv6_cidr_block'] = associate_resp['Ipv6CidrBlockAssociation']['Ipv6CidrBlock']
            if subnet['ipv6_cidr_block_association_set']:
                subnet['ipv6_cidr_block_association_set'][0] = camel_dict_to_snake_dict(associate_resp['Ipv6CidrBlockAssociation'])
            else:
                subnet['ipv6_cidr_block_association_set'].append(camel_dict_to_snake_dict(associate_resp['Ipv6CidrBlockAssociation']))

    return changed
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))
Example #18
0
def create_or_update_role(connection, module):

    params = generate_create_params(module)
    role_name = params['RoleName']
    create_instance_profile = module.params.get('create_instance_profile')
    purge_policies = module.params.get('purge_policies')
    if purge_policies is None:
        purge_policies = True
    managed_policies = module.params.get('managed_policies')
    if managed_policies:
        # Attempt to list the policies early so we don't leave things behind if we can't find them.
        managed_policies = convert_friendly_names_to_arns(
            connection, module, managed_policies)

    changed = False

    # Get role
    role = get_role(connection, module, role_name)

    # If role is None, create it
    if role is None:
        role = create_basic_role(connection, module, params)
        changed = True
    else:
        changed |= update_role_tags(connection, module, params, role)
        changed |= update_role_assumed_policy(connection, module, params, role)
        changed |= update_role_description(connection, module, params, role)
        changed |= update_role_max_session_duration(connection, module, params,
                                                    role)
        changed |= update_role_permissions_boundary(connection, module, params,
                                                    role)

    if create_instance_profile:
        changed |= create_instance_profiles(connection, module, params, role)

    changed |= update_managed_policies(connection, module, params, role,
                                       managed_policies, purge_policies)

    # Get the role again
    if not role.get('MadeInCheckMode', False):
        role = get_role(connection, module, params['RoleName'])
        role['AttachedPolicies'] = get_attached_policy_list(
            connection, module, params['RoleName'])
        role['tags'] = get_role_tags(connection, module)

    module.exit_json(changed=changed,
                     iam_role=camel_dict_to_snake_dict(role,
                                                       ignore_list=['tags']),
                     **camel_dict_to_snake_dict(role, ignore_list=['tags']))
Example #19
0
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 delete_dms_endpoint(connection):
    try:
        endpoint = describe_endpoints(connection,
                                      module.params.get('endpointidentifier'))
        endpoint_arn = endpoint['Endpoints'][0].get('EndpointArn')
        delete_arn = dict(EndpointArn=endpoint_arn)
        if module.params.get('wait'):

            delete_output = connection.delete_endpoint(**delete_arn)
            delete_waiter = get_endpoint_deleted_waiter(connection)
            delete_waiter.wait(Filters=[{
                'Name': 'endpoint-arn',
                'Values': [endpoint_arn]
            }],
                               WaiterConfig={
                                   'Delay': module.params.get('timeout'),
                                   'MaxAttempts': module.params.get('retries')
                               })
            return delete_output
        else:
            return connection.delete_endpoint(**delete_arn)
    except botocore.exceptions.ClientError as e:
        module.fail_json(msg="Failed to delete the  DMS endpoint.",
                         exception=traceback.format_exc(),
                         **camel_dict_to_snake_dict(e.response))
    except botocore.exceptions.BotoCoreError as e:
        module.fail_json(msg="Failed to delete the DMS endpoint.",
                         exception=traceback.format_exc())