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
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
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
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)
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 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
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)
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)
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)
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))
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))
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)
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'
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')
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))
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])
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)
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 ]
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')