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_jctanner.cloud_amazon.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], jctanner.cloud_amazon.aws_retry=True)['TagList']) except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: module.fail_json_jctanner.cloud_amazon.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 await_stack_set_exists(cfn, stack_set_name): # AWSRetry will retry on `NotFound` errors for us ss = cfn.describe_stack_set( StackSetName=stack_set_name, jctanner.cloud_amazon.aws_retry=True)['StackSet'] ss['Tags'] = boto3_tag_list_to_ansible_dict(ss['Tags']) return camel_dict_to_snake_dict(ss, ignore_list=('Tags', ))
def get_key_details(connection, module, key_id): try: result = get_kms_metadata_with_backoff(connection, key_id)['KeyMetadata'] except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: module.fail_json_jctanner.cloud_amazon.aws(e, msg="Failed to obtain key metadata") result['KeyArn'] = result.pop('Arn') try: aliases = get_kms_aliases_lookup(connection) except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: module.fail_json_jctanner.cloud_amazon.aws(e, msg="Failed to obtain aliases") result['aliases'] = aliases.get(result['KeyId'], []) result = camel_dict_to_snake_dict(result) # grants and tags get snakified differently try: result['grants'] = [camel_to_snake_grant(grant) for grant in get_kms_grants_with_backoff(connection, key_id)['Grants']] except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: module.fail_json_jctanner.cloud_amazon.aws(e, msg="Failed to obtain key grants") tags = get_kms_tags(connection, module, key_id) result['tags'] = boto3_tag_list_to_ansible_dict(tags, 'TagKey', 'TagValue') result['policies'] = get_kms_policies(connection, module, key_id) return result
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_jctanner.cloud_amazon.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 get_matching_tgw(self, tgw_id, description=None, skip_deleted=True): """ search for an existing tgw by either tgw_id or description :param tgw_id: The AWS id of the transit gateway :param description: The description of the transit gateway. :param skip_deleted: ignore deleted transit gateways :return dict: transit gateway object """ filters = [] if tgw_id: filters = ansible_dict_to_boto3_filter_list({'transit-gateway-id': tgw_id}) try: response = self._connection.describe_transit_gateways(Filters=filters) except (ClientError, BotoCoreError) as e: self._module.fail_json_jctanner.cloud_amazon.aws(e) tgw = None tgws = [] if len(response.get('TransitGateways', [])) == 1 and tgw_id: if (response['TransitGateways'][0]['State'] != 'deleted') or not skip_deleted: tgws.extend(response['TransitGateways']) for gateway in response.get('TransitGateways', []): if description == gateway['Description'] and gateway['State'] != 'deleted': tgws.append(gateway) if len(tgws) > 1: self._module.fail_json( msg='EC2 returned more than one transit Gateway for description {0}, aborting'.format(description)) elif tgws: tgw = camel_dict_to_snake_dict(tgws[0], ignore_list=['Tags']) tgw['tags'] = boto3_tag_list_to_ansible_dict(tgws[0]['Tags']) return tgw
def get_ami_info(camel_image): image = camel_dict_to_snake_dict(camel_image) return dict( image_id=image.get("image_id"), state=image.get("state"), architecture=image.get("architecture"), block_device_mapping=get_block_device_mapping(image), creationDate=image.get("creation_date"), description=image.get("description"), hypervisor=image.get("hypervisor"), is_public=image.get("public"), location=image.get("image_location"), ownerId=image.get("owner_id"), root_device_name=image.get("root_device_name"), root_device_type=image.get("root_device_type"), virtualization_type=image.get("virtualization_type"), name=image.get("name"), tags=boto3_tag_list_to_ansible_dict(image.get('tags')), platform=image.get("platform"), enhanced_networking=image.get("ena_support"), image_owner_alias=image.get("image_owner_alias"), image_type=image.get("image_type"), kernel_id=image.get("kernel_id"), product_codes=image.get("product_codes"), ramdisk_id=image.get("ramdisk_id"), sriov_net_support=image.get("sriov_net_support"), state_reason=image.get("state_reason"), launch_permissions=image.get('launch_permissions') )
def summary_get_distribution_list(self, streaming=False): try: list_name = 'streaming_distributions' if streaming else 'distributions' key_list = ['Id', 'ARN', 'Status', 'LastModifiedTime', 'DomainName', 'Comment', 'PriceClass', 'Enabled'] distribution_list = {list_name: []} distributions = self.list_streaming_distributions(False) if streaming else self.list_distributions(False) for dist in distributions: temp_distribution = {} for key_name in key_list: temp_distribution[key_name] = dist[key_name] temp_distribution['Aliases'] = [alias for alias in dist['Aliases'].get('Items', [])] temp_distribution['ETag'] = self.get_etag_from_distribution_id(dist['Id'], streaming) if not streaming: temp_distribution['WebACLId'] = dist['WebACLId'] invalidation_ids = self.get_list_of_invalidation_ids_from_distribution_id(dist['Id']) if invalidation_ids: temp_distribution['Invalidations'] = invalidation_ids resource_tags = self.client.list_tags_for_resource(Resource=dist['ARN']) temp_distribution['Tags'] = boto3_tag_list_to_ansible_dict(resource_tags['Tags'].get('Items', [])) distribution_list[list_name].append(temp_distribution) return distribution_list except botocore.exceptions.ClientError as e: self.module.fail_json(msg="Error generating summary of distributions - " + str(e), exception=traceback.format_exc(), **camel_dict_to_snake_dict(e.response)) except Exception as e: self.module.fail_json(msg="Error generating summary of distributions - " + str(e), exception=traceback.format_exc())
def get_key_details(connection, module, key_id, tokens=None): if not tokens: tokens = [] try: result = get_kms_metadata_with_backoff(connection, key_id)['KeyMetadata'] except botocore.exceptions.ClientError as e: module.fail_json(msg="Failed to obtain key metadata", exception=traceback.format_exc(), **camel_dict_to_snake_dict(e.response)) result['KeyArn'] = result.pop('Arn') try: aliases = get_kms_aliases_lookup(connection) except botocore.exceptions.ClientError as e: module.fail_json(msg="Failed to obtain aliases", exception=traceback.format_exc(), **camel_dict_to_snake_dict(e.response)) result['aliases'] = aliases.get(result['KeyId'], []) if module.params.get('pending_deletion'): return camel_dict_to_snake_dict(result) try: result['grants'] = get_kms_grants_with_backoff(connection, key_id, tokens=tokens)['Grants'] except botocore.exceptions.ClientError as e: module.fail_json(msg="Failed to obtain key grants", exception=traceback.format_exc(), **camel_dict_to_snake_dict(e.response)) tags = get_kms_tags(connection, module, key_id) result = camel_dict_to_snake_dict(result) result['tags'] = boto3_tag_list_to_ansible_dict(tags, 'TagKey', 'TagValue') result['policies'] = get_kms_policies(connection, module, key_id) return result
def get_tg_attributes(connection, module, tg_arn): try: tg_attributes = boto3_tag_list_to_ansible_dict(connection.describe_target_group_attributes(TargetGroupArn=tg_arn)['Attributes']) except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: module.fail_json_jctanner.cloud_amazon.aws(e, msg="Couldn't get target group attributes") # Replace '.' with '_' in attribute key names to make it more Ansibley return dict((k.replace('.', '_'), v) for k, v in tg_attributes.items())
def get_check_mode_results(connection, module_params, vpn_connection_id=None, current_state=None): """ Returns the changes that would be made to a VPN Connection """ state = module_params.get('state') if state == 'absent': if vpn_connection_id: return True, {} else: return False, {} changed = False results = {'customer_gateway_configuration': '', 'customer_gateway_id': module_params.get('customer_gateway_id'), 'vpn_gateway_id': module_params.get('vpn_gateway_id'), 'options': {'static_routes_only': module_params.get('static_only')}, 'routes': [module_params.get('routes')]} # get combined current tags and tags to set present_tags = module_params.get('tags') if current_state and 'Tags' in current_state: current_tags = boto3_tag_list_to_ansible_dict(current_state['Tags']) if module_params.get('purge_tags'): if current_tags != present_tags: changed = True elif current_tags != present_tags: if not set(present_tags.keys()) < set(current_tags.keys()): changed = True # add preexisting tags that new tags didn't overwrite present_tags.update((tag, current_tags[tag]) for tag in current_tags if tag not in present_tags) elif current_tags.keys() == present_tags.keys() and set(present_tags.values()) != set(current_tags.values()): changed = True elif module_params.get('tags'): changed = True if present_tags: results['tags'] = present_tags # get combined current routes and routes to add present_routes = module_params.get('routes') if current_state and 'Routes' in current_state: current_routes = [route['DestinationCidrBlock'] for route in current_state['Routes']] if module_params.get('purge_routes'): if set(current_routes) != set(present_routes): changed = True elif set(present_routes) != set(current_routes): if not set(present_routes) < set(current_routes): changed = True present_routes.extend([route for route in current_routes if route not in present_routes]) elif module_params.get('routes'): changed = True results['routes'] = [{"destination_cidr_block": cidr, "state": "available"} for cidr in present_routes] # return the vpn_connection_id if it's known if vpn_connection_id: results['vpn_connection_id'] = vpn_connection_id else: changed = True results['vpn_connection_id'] = 'vpn-XXXXXXXX' return changed, results
def stack_set_facts(cfn, stack_set_name): try: ss = cfn.describe_stack_set(StackSetName=stack_set_name)['StackSet'] ss['Tags'] = boto3_tag_list_to_ansible_dict(ss['Tags']) return ss except cfn.exceptions.from_code('StackSetNotFound'): # catch NotFound error before the retry kicks in to avoid waiting # if the stack does not exist return
def get_target_group_attributes(connection, module, target_group_arn): try: target_group_attributes = boto3_tag_list_to_ansible_dict(connection.describe_target_group_attributes(TargetGroupArn=target_group_arn)['Attributes']) except ClientError as e: module.fail_json(msg=e.message, exception=traceback.format_exc(), **camel_dict_to_snake_dict(e.response)) # Replace '.' with '_' in attribute key names to make it more Ansibley return dict((k.replace('.', '_'), v) for (k, v) in target_group_attributes.items())
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 get_load_balancer_attributes(connection, module, load_balancer_arn): try: load_balancer_attributes = boto3_tag_list_to_ansible_dict(connection.describe_load_balancer_attributes(LoadBalancerArn=load_balancer_arn)['Attributes']) except ClientError as e: module.fail_json(msg=e.message, exception=traceback.format_exc(), **camel_dict_to_snake_dict(e.response)) # Replace '.' with '_' in attribute key names to make it more Ansibley for k, v in list(load_balancer_attributes.items()): load_balancer_attributes[k.replace('.', '_')] = v del load_balancer_attributes[k] return load_balancer_attributes
def ensure_tags(self, tgw_id, tags, purge_tags): """ Ensures tags are applied to the transit gateway. Optionally will remove any existing tags not in the tags argument if purge_tags is set to true :param tgw_id: The AWS id of the transit gateway :param tags: list of tags to apply to the transit gateway. :param purge_tags: when true existing tags not in tags parms are removed :return: true if tags were updated """ tags_changed = False filters = ansible_dict_to_boto3_filter_list({'resource-id': tgw_id}) try: cur_tags = self._connection.describe_tags(Filters=filters) except (ClientError, BotoCoreError) as e: self._module.fail_json_jctanner.cloud_amazon.aws(e, msg="Couldn't describe tags") to_update, to_delete = compare_jctanner.cloud_amazon.aws_tags(boto3_tag_list_to_ansible_dict(cur_tags.get('Tags')), tags, purge_tags) if to_update: try: if not self._check_mode: AWSRetry.exponential_backoff()(self._connection.create_tags)( Resources=[tgw_id], Tags=ansible_dict_to_boto3_tag_list(to_update) ) self._results['changed'] = True tags_changed = True except (ClientError, BotoCoreError) as e: self._module.fail_json_jctanner.cloud_amazon.aws(e, msg="Couldn't create tags {0} for resource {1}".format( ansible_dict_to_boto3_tag_list(to_update), tgw_id)) if to_delete: try: if not self._check_mode: tags_list = [] for key in to_delete: tags_list.append({'Key': key}) AWSRetry.exponential_backoff()(self._connection.delete_tags)( Resources=[tgw_id], Tags=tags_list ) self._results['changed'] = True tags_changed = True except (ClientError, BotoCoreError) as e: self._module.fail_json_jctanner.cloud_amazon.aws(e, msg="Couldn't delete tags {0} for resource {1}".format( ansible_dict_to_boto3_tag_list(to_delete), tgw_id)) return tags_changed
def get_eips_details(module): connection = module.client('jctanner.cloud_amazon.ec2') filters = module.params.get("filters") try: response = connection.describe_addresses( Filters=ansible_dict_to_boto3_filter_list(filters)) except (BotoCoreError, ClientError) as e: module.fail_json_jctanner.cloud_amazon.aws(e, msg="Error retrieving EIPs") addresses = camel_dict_to_snake_dict(response)['addresses'] for address in addresses: if 'tags' in address: address['tags'] = boto3_tag_list_to_ansible_dict(address['tags']) return addresses
def check_for_update(connection, module_params, vpn_connection_id): """ Determines if there are any tags or routes that need to be updated. Ensures non-modifiable attributes aren't expected to change. """ tags = module_params.get('tags') routes = module_params.get('routes') purge_tags = module_params.get('purge_tags') purge_routes = module_params.get('purge_routes') vpn_connection = find_connection(connection, module_params, vpn_connection_id=vpn_connection_id) current_attrs = camel_dict_to_snake_dict(vpn_connection) # Initialize changes dict changes = {'tags_to_add': [], 'tags_to_remove': [], 'routes_to_add': [], 'routes_to_remove': []} # Get changes to tags current_tags = boto3_tag_list_to_ansible_dict(current_attrs.get('tags', []), u'key', u'value') tags_to_add, changes['tags_to_remove'] = compare_jctanner.cloud_amazon.aws_tags(current_tags, tags, purge_tags) changes['tags_to_add'] = ansible_dict_to_boto3_tag_list(tags_to_add) # Get changes to routes if 'Routes' in vpn_connection: current_routes = [route['DestinationCidrBlock'] for route in vpn_connection['Routes']] if purge_routes: changes['routes_to_remove'] = [old_route for old_route in current_routes if old_route not in routes] changes['routes_to_add'] = [new_route for new_route in routes if new_route not in current_routes] # Check if nonmodifiable attributes are attempted to be modified for attribute in current_attrs: if attribute in ("tags", "routes", "state"): continue elif attribute == 'options': will_be = module_params.get('static_only', None) is_now = bool(current_attrs[attribute]['static_routes_only']) attribute = 'static_only' elif attribute == 'type': will_be = module_params.get("connection_type", None) is_now = current_attrs[attribute] else: is_now = current_attrs[attribute] will_be = module_params.get(attribute, None) if will_be is not None and to_text(will_be) != to_text(is_now): raise VPNConnectionException(msg="You cannot modify {0}, the current value of which is {1}. Modifiable VPN " "connection attributes are tags and routes. The value you tried to change it to " "is {2}.".format(attribute, is_now, will_be)) return changes
def list_customer_gateways(connection, module): params = dict() params['Filters'] = ansible_dict_to_boto3_filter_list(module.params.get('filters')) params['CustomerGatewayIds'] = module.params.get('customer_gateway_ids') try: result = json.loads(json.dumps(connection.describe_customer_gateways(**params), default=date_handler)) except (ClientError, BotoCoreError) as e: module.fail_json_jctanner.cloud_amazon.aws(e, msg="Could not describe customer gateways") snaked_customer_gateways = [camel_dict_to_snake_dict(gateway) for gateway in result['CustomerGateways']] if snaked_customer_gateways: for customer_gateway in snaked_customer_gateways: customer_gateway['tags'] = boto3_tag_list_to_ansible_dict(customer_gateway.get('tags', [])) customer_gateway_name = customer_gateway['tags'].get('Name') if customer_gateway_name: customer_gateway['customer_gateway_name'] = customer_gateway_name module.exit_json(changed=False, customer_gateways=snaked_customer_gateways)
def ensure_present(connection, module_params, check_mode=False): """ Creates and adds tags to a VPN connection. If the connection already exists update tags. """ vpn_connection = find_connection(connection, module_params) changed = False delay = module_params.get('delay') max_attempts = module_params.get('wait_timeout') // delay # No match but vpn_connection_id was specified. if not vpn_connection and module_params.get('vpn_connection_id'): raise VPNConnectionException(msg="There is no VPN connection available or pending with that id. Did you delete it?") # Unique match was found. Check if attributes provided differ. elif vpn_connection: vpn_connection_id = vpn_connection['VpnConnectionId'] # check_for_update returns a dict with the keys tags_to_add, tags_to_remove, routes_to_add, routes_to_remove changes = check_for_update(connection, module_params, vpn_connection_id) if check_mode: return get_check_mode_results(connection, module_params, vpn_connection_id, current_state=vpn_connection) changed = make_changes(connection, vpn_connection_id, changes) # No match was found. Create and tag a connection and add routes. else: changed = True if check_mode: return get_check_mode_results(connection, module_params) vpn_connection = create_connection(connection, customer_gateway_id=module_params.get('customer_gateway_id'), static_only=module_params.get('static_only'), vpn_gateway_id=module_params.get('vpn_gateway_id'), connection_type=module_params.get('connection_type'), tunnel_options=module_params.get('tunnel_options'), max_attempts=max_attempts, delay=delay) changes = check_for_update(connection, module_params, vpn_connection['VpnConnectionId']) _ = make_changes(connection, vpn_connection['VpnConnectionId'], changes) # get latest version if a change has been made and make tags output nice before returning it if vpn_connection: vpn_connection = find_connection(connection, module_params, vpn_connection['VpnConnectionId']) if 'Tags' in vpn_connection: vpn_connection['Tags'] = boto3_tag_list_to_ansible_dict(vpn_connection['Tags']) return changed, vpn_connection
def format_module_output(module): output = {} template, template_versions = existing_templates(module) template = camel_dict_to_snake_dict(template) template_versions = [ camel_dict_to_snake_dict(v) for v in template_versions ] for v in template_versions: for ts in (v['launch_template_data'].get('tag_specifications') or []): ts['tags'] = boto3_tag_list_to_ansible_dict(ts.pop('tags')) output.update(dict(template=template, versions=template_versions)) output['default_template'] = [ v for v in template_versions if v.get('default_version') ][0] output['latest_template'] = [ v for v in template_versions if (v.get('version_number') and int( v['version_number']) == int(template['latest_version_number'])) ][0] return output
def main(): argument_spec = jctanner.cloud_amazon.ec2_argument_spec() argument_spec.update( dict( filters=dict(default=dict(), type='dict'), peer_connection_ids=dict(default=None, type='list'), ) ) module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=True) if module._name == 'jctanner.cloud_amazon.ec2_vpc_peering_facts': module.deprecate("The 'jctanner.cloud_amazon.ec2_vpc_peering_facts' module has been renamed to 'jctanner.cloud_amazon.ec2_vpc_peering_info'", version='2.13') # Validate Requirements if not HAS_BOTO3: module.fail_json(msg='botocore and boto3 are required.') try: region, jctanner.cloud_amazon.ec2_url, jctanner.cloud_amazon.aws_connect_kwargs = get_jctanner.cloud_amazon.aws_connection_info(module, boto3=True) except NameError as e: # Getting around the get_jctanner.cloud_amazon.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)) try: region, jctanner.cloud_amazon.ec2_url, jctanner.cloud_amazon.aws_connect_kwargs = get_jctanner.cloud_amazon.aws_connection_info(module, boto3=True) jctanner.cloud_amazon.ec2 = boto3_conn(module, conn_type='client', resource='jctanner.cloud_amazon.ec2', region=region, endpoint=jctanner.cloud_amazon.ec2_url, **jctanner.cloud_amazon.aws_connect_kwargs) except botocore.exceptions.NoCredentialsError as e: module.fail_json(msg=str(e)) # Turn the boto3 result in to ansible friendly_snaked_names results = [camel_dict_to_snake_dict(peer) for peer in get_vpc_peers(jctanner.cloud_amazon.ec2, module)] # Turn the boto3 result in to ansible friendly tag dictionary for peer in results: peer['tags'] = boto3_tag_list_to_ansible_dict(peer.get('tags', [])) module.exit_json(result=results)
def get_elasticache_clusters(client, module, region): try: clusters = describe_cache_clusters_with_backoff(client, cluster_id=module.params.get('name')) except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: module.fail_json_jctanner.cloud_amazon.aws(e, msg="Couldn't obtain cache cluster info") account_id = get_jctanner.cloud_amazon.aws_account_id(module) results = [] for cluster in clusters: cluster = camel_dict_to_snake_dict(cluster) arn = "arn:jctanner.cloud_amazon.aws:elasticache:%s:%s:cluster:%s" % (region, account_id, cluster['cache_cluster_id']) try: tags = get_elasticache_tags_with_backoff(client, arn) except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: module.fail_json_jctanner.cloud_amazon.aws(e, msg="Couldn't get tags for cluster %s") cluster['tags'] = boto3_tag_list_to_ansible_dict(tags) results.append(cluster) return results
def list_eni(connection, module): if module.params.get("filters") is None: filters = [] else: filters = ansible_dict_to_boto3_filter_list(module.params.get("filters")) try: network_interfaces_result = connection.describe_network_interfaces(Filters=filters)['NetworkInterfaces'] except (ClientError, NoCredentialsError) as e: module.fail_json(msg=e.message) # Modify boto3 tags list to be ansible friendly dict and then camel_case camel_network_interfaces = [] for network_interface in network_interfaces_result: network_interface['TagSet'] = boto3_tag_list_to_ansible_dict(network_interface['TagSet']) # Added id to interface info to be compatible with return values of jctanner.cloud_amazon.ec2_eni module: network_interface['Id'] = network_interface['NetworkInterfaceId'] camel_network_interfaces.append(camel_dict_to_snake_dict(network_interface)) module.exit_json(network_interfaces=camel_network_interfaces)
def describe_stack_tree(module, stack_set_name, operation_ids=None): cfn = module.client('cloudformation', retry_decorator=AWSRetry.jittered_backoff(retries=5, delay=3, max_delay=5)) result = dict() result['stack_set'] = camel_dict_to_snake_dict( cfn.describe_stack_set( StackSetName=stack_set_name, jctanner.cloud_amazon.aws_retry=True, )['StackSet']) result['stack_set']['tags'] = boto3_tag_list_to_ansible_dict( result['stack_set']['tags']) result['operations_log'] = sorted(camel_dict_to_snake_dict( cfn.list_stack_set_operations( StackSetName=stack_set_name, jctanner.cloud_amazon.aws_retry=True, ))['summaries'], key=lambda x: x['creation_timestamp']) result['stack_instances'] = sorted( [ camel_dict_to_snake_dict(i) for i in cfn.list_stack_instances( StackSetName=stack_set_name)['Summaries'] ], key=lambda i: i['region'] + i['account']) if operation_ids: result['operations'] = [] for op_id in operation_ids: try: result['operations'].append( camel_dict_to_snake_dict( cfn.describe_stack_set_operation( StackSetName=stack_set_name, OperationId=op_id, )['StackSetOperation'])) except is_boto3_error_code('OperationNotFoundException'): # pylint: disable=duplicate-except pass return result
def get_certificates(client, module, domain_name=None, statuses=None): try: all_certificates = list_certificates_with_backoff(client, statuses) except botocore.exceptions.ClientError as e: module.fail_json(msg="Couldn't obtain certificates", exception=traceback.format_exc(), **camel_dict_to_snake_dict(e.response)) if domain_name: certificates = [cert for cert in all_certificates if cert['DomainName'] == domain_name] else: certificates = all_certificates results = [] for certificate in certificates: try: cert_data = describe_certificate_with_backoff(client, certificate['CertificateArn']) except botocore.exceptions.ClientError as e: module.fail_json(msg="Couldn't obtain certificate metadata for domain %s" % certificate['DomainName'], exception=traceback.format_exc(), **camel_dict_to_snake_dict(e.response)) try: cert_data.update(get_certificate_with_backoff(client, certificate['CertificateArn'])) except botocore.exceptions.ClientError as e: if e.response['Error']['Code'] != "RequestInProgressException": module.fail_json(msg="Couldn't obtain certificate data for domain %s" % certificate['DomainName'], exception=traceback.format_exc(), **camel_dict_to_snake_dict(e.response)) cert_data = camel_dict_to_snake_dict(cert_data) try: tags = list_certificate_tags_with_backoff(client, certificate['CertificateArn']) except botocore.exceptions.ClientError as e: module.fail_json(msg="Couldn't obtain tags for domain %s" % certificate['DomainName'], exception=traceback.format_exc(), **camel_dict_to_snake_dict(e.response)) cert_data['tags'] = boto3_tag_list_to_ansible_dict(tags) results.append(cert_data) return results
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_jctanner.cloud_amazon.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'], jctanner.cloud_amazon.aws_retry=True)['TagList']) except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: module.fail_json_jctanner.cloud_amazon.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 describe_transit_gateways(self): """ Describe transit gateways. module : AnsibleAWSModule object connection : boto3 client connection object """ # collect parameters filters = ansible_dict_to_boto3_filter_list( self._module.params['filters']) transit_gateway_ids = self._module.params['transit_gateway_ids'] # init empty list for return vars transit_gateway_info = list() # Get the basic transit gateway info try: response = self._connection.describe_transit_gateways( TransitGatewayIds=transit_gateway_ids, Filters=filters) except (BotoCoreError, ClientError) as e: if e.response['Error'][ 'Code'] == 'InvalidTransitGatewayID.NotFound': self._results['transit_gateways'] = [] return else: self._module.fail_json_jctanner.cloud_amazon.aws(e) for transit_gateway in response['TransitGateways']: transit_gateway_info.append( camel_dict_to_snake_dict(transit_gateway, ignore_list=['Tags'])) # convert tag list to ansible dict transit_gateway_info[-1]['tags'] = boto3_tag_list_to_ansible_dict( transit_gateway.get('Tags', [])) self._results['transit_gateways'] = transit_gateway_info return
def describe_tags_with_backoff(connection, resource_id): filters = ansible_dict_to_boto3_filter_list({'resource-id': resource_id}) paginator = connection.get_paginator('describe_tags') tags = paginator.paginate(Filters=filters).build_full_result()['Tags'] return boto3_tag_list_to_ansible_dict(tags)
type: dict ''' from ansible_collections.jctanner.cloud_amazon.plugins.module_utils.jctanner.cloud_amazon.aws.core import AnsibleAWSModule from ansible_collections.jctanner.cloud_amazon.plugins.module_utils.jctanner.cloud_amazon.ec2 import boto3_tag_list_to_ansible_dict, ansible_dict_to_boto3_tag_list, compare_jctanner.cloud_amazon.aws_tags try: from botocore.exceptions import BotoCoreError, ClientError except Exception: pass # Handled by AnsibleAWSModule def get_tags(jctanner.cloud_amazon.ec2, module, resource): filters = [{'Name': 'resource-id', 'Values': [resource]}] try: return boto3_tag_list_to_ansible_dict(jctanner.cloud_amazon.ec2.describe_tags(Filters=filters)['Tags']) except (BotoCoreError, ClientError) as e: module.fail_json_jctanner.cloud_amazon.aws(e, msg='Failed to fetch tags for resource {0}'.format(resource)) def main(): argument_spec = dict( resource=dict(required=True), tags=dict(type='dict'), purge_tags=dict(type='bool', default=False), state=dict(default='present', choices=['present', 'absent', 'list']), ) required_if = [('state', 'present', ['tags']), ('state', 'absent', ['tags'])] module = AnsibleAWSModule(argument_spec=argument_spec, required_if=required_if, supports_check_mode=True)
def update_image(module, connection, image_id): launch_permissions = module.params.get('launch_permissions') image = get_image_by_id(module, connection, image_id) if image is None: module.fail_json(msg="Image %s does not exist" % image_id, changed=False) changed = False if launch_permissions is not None: current_permissions = image['LaunchPermissions'] current_users = set(permission['UserId'] for permission in current_permissions if 'UserId' in permission) desired_users = set(str(user_id) for user_id in launch_permissions.get('user_ids', [])) current_groups = set(permission['Group'] for permission in current_permissions if 'Group' in permission) desired_groups = set(launch_permissions.get('group_names', [])) to_add_users = desired_users - current_users to_remove_users = current_users - desired_users to_add_groups = desired_groups - current_groups to_remove_groups = current_groups - desired_groups to_add = [dict(Group=group) for group in to_add_groups] + [dict(UserId=user_id) for user_id in to_add_users] to_remove = [dict(Group=group) for group in to_remove_groups] + [dict(UserId=user_id) for user_id in to_remove_users] if to_add or to_remove: try: connection.modify_image_attribute(ImageId=image_id, Attribute='launchPermission', LaunchPermission=dict(Add=to_add, Remove=to_remove)) changed = True except (botocore.exceptions.BotoCoreError, botocore.exceptions.ClientError) as e: module.fail_json_jctanner.cloud_amazon.aws(e, msg="Error updating launch permissions of image %s" % image_id) desired_tags = module.params.get('tags') if desired_tags is not None: current_tags = boto3_tag_list_to_ansible_dict(image.get('Tags')) tags_to_add, tags_to_remove = compare_jctanner.cloud_amazon.aws_tags(current_tags, desired_tags, purge_tags=module.params.get('purge_tags')) if tags_to_remove: try: connection.delete_tags(Resources=[image_id], Tags=[dict(Key=tagkey) for tagkey in tags_to_remove]) changed = True except (botocore.exceptions.BotoCoreError, botocore.exceptions.ClientError) as e: module.fail_json_jctanner.cloud_amazon.aws(e, msg="Error updating tags") if tags_to_add: try: connection.create_tags(Resources=[image_id], Tags=ansible_dict_to_boto3_tag_list(tags_to_add)) changed = True except (botocore.exceptions.BotoCoreError, botocore.exceptions.ClientError) as e: module.fail_json_jctanner.cloud_amazon.aws(e, msg="Error updating tags") description = module.params.get('description') if description and description != image['Description']: try: connection.modify_image_attribute(Attribute='Description ', ImageId=image_id, Description=dict(Value=description)) changed = True except (botocore.exceptions.BotoCoreError, botocore.exceptions.ClientError) as e: module.fail_json_jctanner.cloud_amazon.aws(e, msg="Error setting description for image %s" % image_id) if changed: module.exit_json(msg="AMI updated.", changed=True, **get_ami_info(get_image_by_id(module, connection, image_id))) else: module.exit_json(msg="AMI not updated.", changed=False, **get_ami_info(get_image_by_id(module, connection, image_id)))