From ab3281407d84dcaffa72702f4682c730644b607b Mon Sep 17 00:00:00 2001 From: Bikouo Aubin <79859644+abikouo@users.noreply.github.com> Date: Wed, 1 Feb 2023 13:05:37 +0100 Subject: [PATCH] update module using module_utils/cloudfront_facts.py (#1596) update module using module_utils/cloudfront_facts.py Depends-On: ansible-collections/amazon.aws#1265 SUMMARY update cloudfront_* modules, fix some bugs and add integration tests ISSUE TYPE Feature Pull Request Reviewed-by: Alina Buzachis Reviewed-by: Bikouo Aubin --- cloudfront_distribution.py | 12 +- cloudfront_distribution_info.py | 306 +++------------------------ cloudfront_invalidation.py | 38 ++-- cloudfront_origin_access_identity.py | 68 +++--- 4 files changed, 88 insertions(+), 336 deletions(-) diff --git a/cloudfront_distribution.py b/cloudfront_distribution.py index d2e00f0221c..f7ff3b51553 100644 --- a/cloudfront_distribution.py +++ b/cloudfront_distribution.py @@ -2105,12 +2105,12 @@ def validate_attribute_with_allowed_values(self, attribute, attribute_name, allo def validate_distribution_from_caller_reference(self, caller_reference): try: - distributions = self.__cloudfront_facts_mgr.list_distributions(False) + distributions = self.__cloudfront_facts_mgr.list_distributions(keyed=False) distribution_name = 'Distribution' distribution_config_name = 'DistributionConfig' distribution_ids = [dist.get('Id') for dist in distributions] for distribution_id in distribution_ids: - distribution = self.__cloudfront_facts_mgr.get_distribution(distribution_id) + distribution = self.__cloudfront_facts_mgr.get_distribution(id=distribution_id) if distribution is not None: distribution_config = distribution[distribution_name].get(distribution_config_name) if distribution_config is not None and distribution_config.get('CallerReference') == caller_reference: @@ -2128,13 +2128,13 @@ def validate_distribution_from_aliases_caller_reference(self, distribution_id, a if aliases and distribution_id is None: distribution_id = self.validate_distribution_id_from_alias(aliases) if distribution_id: - return self.__cloudfront_facts_mgr.get_distribution(distribution_id) + return self.__cloudfront_facts_mgr.get_distribution(id=distribution_id) return None except Exception as e: self.module.fail_json_aws(e, msg="Error validating distribution_id from alias, aliases and caller reference") def validate_distribution_id_from_alias(self, aliases): - distributions = self.__cloudfront_facts_mgr.list_distributions(False) + distributions = self.__cloudfront_facts_mgr.list_distributions(keyed=False) if distributions: for distribution in distributions: distribution_aliases = distribution.get('Aliases', {}).get('Items', []) @@ -2253,12 +2253,12 @@ def main(): if not (update or create or delete): module.exit_json(changed=False) + config = {} if update or delete: config = distribution['Distribution']['DistributionConfig'] e_tag = distribution['ETag'] distribution_id = distribution['Distribution']['Id'] - else: - config = dict() + if update: config = camel_dict_to_snake_dict(config, reversible=True) diff --git a/cloudfront_distribution_info.py b/cloudfront_distribution_info.py index 8898e895029..179e572e0c9 100644 --- a/cloudfront_distribution_info.py +++ b/cloudfront_distribution_info.py @@ -3,6 +3,7 @@ # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) from __future__ import (absolute_import, division, print_function) + __metaclass__ = type @@ -244,265 +245,18 @@ type: dict ''' -import traceback - -try: - import botocore -except ImportError: - pass # Handled by AnsibleAWSModule - from ansible_collections.community.aws.plugins.module_utils.modules import AnsibleCommunityAWSModule as AnsibleAWSModule -from ansible_collections.amazon.aws.plugins.module_utils.ec2 import boto3_tag_list_to_ansible_dict -from ansible_collections.amazon.aws.plugins.module_utils.ec2 import AWSRetry - - -class CloudFrontServiceManager: - """Handles CloudFront Services""" - - def __init__(self, module): - self.module = module - - try: - self.client = module.client('cloudfront', retry_decorator=AWSRetry.jittered_backoff()) - except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: - module.fail_json_aws(e, msg='Failed to connect to AWS') - - def get_distribution(self, distribution_id): - try: - distribution = self.client.get_distribution(aws_retry=True, Id=distribution_id) - return distribution - except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: - self.module.fail_json_aws(e, msg="Error describing distribution") - - def get_distribution_config(self, distribution_id): - try: - distribution = self.client.get_distribution_config(aws_retry=True, Id=distribution_id) - return distribution - except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: - self.module.fail_json_aws(e, msg="Error describing distribution configuration") - - def get_origin_access_identity(self, origin_access_identity_id): - try: - origin_access_identity = self.client.get_cloud_front_origin_access_identity(aws_retry=True, Id=origin_access_identity_id) - return origin_access_identity - except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: - self.module.fail_json_aws(e, msg="Error describing origin access identity") - - def get_origin_access_identity_config(self, origin_access_identity_id): - try: - origin_access_identity = self.client.get_cloud_front_origin_access_identity_config(aws_retry=True, Id=origin_access_identity_id) - return origin_access_identity - except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: - self.module.fail_json_aws(e, msg="Error describing origin access identity configuration") - - def get_invalidation(self, distribution_id, invalidation_id): - try: - invalidation = self.client.get_invalidation(aws_retry=True, DistributionId=distribution_id, Id=invalidation_id) - return invalidation - except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: - self.module.fail_json_aws(e, msg="Error describing invalidation") - - def get_streaming_distribution(self, distribution_id): - try: - streaming_distribution = self.client.get_streaming_distribution(aws_retry=True, Id=distribution_id) - return streaming_distribution - except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: - self.module.fail_json_aws(e, msg="Error describing streaming distribution") - - def get_streaming_distribution_config(self, distribution_id): - try: - streaming_distribution = self.client.get_streaming_distribution_config(aws_retry=True, Id=distribution_id) - return streaming_distribution - except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: - self.module.fail_json_aws(e, msg="Error describing streaming distribution") - - # Split out paginator to allow for the backoff decorator to function - @AWSRetry.jittered_backoff() - def _paginated_result(self, paginator_name, **params): - paginator = self.client.get_paginator(paginator_name) - results = paginator.paginate(**params).build_full_result() - return results - - def list_origin_access_identities(self): - try: - results = self._paginated_result('list_cloud_front_origin_access_identities') - origin_access_identity_list = results.get('CloudFrontOriginAccessIdentityList', {'Items': []}) - - if len(origin_access_identity_list['Items']) > 0: - return origin_access_identity_list['Items'] - return {} - except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: - self.module.fail_json_aws(e, msg="Error listing cloud front origin access identities") - - def list_distributions(self, keyed=True): - try: - results = self._paginated_result('list_distributions') - distribution_list = results.get('DistributionList', {'Items': []}) - - if len(distribution_list['Items']) > 0: - distribution_list = distribution_list['Items'] - else: - return {} - - if not keyed: - return distribution_list - return self.keyed_list_helper(distribution_list) - except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: - self.module.fail_json_aws(e, msg="Error listing distributions") - - def list_distributions_by_web_acl_id(self, web_acl_id): - try: - results = self._paginated_result('list_cloud_front_origin_access_identities', WebAclId=web_acl_id) - distribution_list = results.get('DistributionList', {'Items': []}) - - if len(distribution_list['Items']) > 0: - distribution_list = distribution_list['Items'] - else: - return {} - return self.keyed_list_helper(distribution_list) - except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: - self.module.fail_json_aws(e, msg="Error listing distributions by web acl id") - - def list_invalidations(self, distribution_id): - try: - results = self._paginated_result('list_invalidations', DistributionId=distribution_id) - invalidation_list = results.get('InvalidationList', {'Items': []}) - - if len(invalidation_list['Items']) > 0: - return invalidation_list['Items'] - return {} - except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: - self.module.fail_json_aws(e, msg="Error listing invalidations") - - def list_streaming_distributions(self, keyed=True): - try: - results = self._paginated_result('list_streaming_distributions') - streaming_distribution_list = results.get('StreamingDistributionList', {'Items': []}) - - if len(streaming_distribution_list['Items']) > 0: - streaming_distribution_list = streaming_distribution_list['Items'] - else: - return {} - - if not keyed: - return streaming_distribution_list - return self.keyed_list_helper(streaming_distribution_list) - except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: - self.module.fail_json_aws(e, msg="Error listing streaming distributions") - - def summary(self): - summary_dict = {} - summary_dict.update(self.summary_get_distribution_list(False)) - summary_dict.update(self.summary_get_distribution_list(True)) - summary_dict.update(self.summary_get_origin_access_identity_list()) - return summary_dict - - def summary_get_origin_access_identity_list(self): - try: - origin_access_identity_list = {'origin_access_identities': []} - origin_access_identities = self.list_origin_access_identities() - for origin_access_identity in origin_access_identities: - oai_id = origin_access_identity['Id'] - oai_full_response = self.get_origin_access_identity(oai_id) - oai_summary = {'Id': oai_id, 'ETag': oai_full_response['ETag']} - origin_access_identity_list['origin_access_identities'].append(oai_summary) - return origin_access_identity_list - except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: - self.module.fail_json_aws(e, msg="Error generating summary of origin access identities") - - 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, botocore.exceptions.BotoCoreError) as e: - self.module.fail_json_aws(e, msg="Error generating summary of distributions") - except Exception as e: - self.module.fail_json(msg="Error generating summary of distributions - " + str(e), - exception=traceback.format_exc()) - - def get_etag_from_distribution_id(self, distribution_id, streaming): - distribution = {} - if not streaming: - distribution = self.get_distribution(distribution_id) - else: - distribution = self.get_streaming_distribution(distribution_id) - return distribution['ETag'] - - def get_list_of_invalidation_ids_from_distribution_id(self, distribution_id): - try: - invalidation_ids = [] - invalidations = self.list_invalidations(distribution_id) - for invalidation in invalidations: - invalidation_ids.append(invalidation['Id']) - return invalidation_ids - except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: - self.module.fail_json_aws(e, msg="Error getting list of invalidation ids") - - def get_distribution_id_from_domain_name(self, domain_name): - try: - distribution_id = "" - distributions = self.list_distributions(False) - distributions += self.list_streaming_distributions(False) - for dist in distributions: - if 'Items' in dist['Aliases']: - for alias in dist['Aliases']['Items']: - if str(alias).lower() == domain_name.lower(): - distribution_id = dist['Id'] - break - return distribution_id - except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: - self.module.fail_json_aws(e, msg="Error getting distribution id from domain name") - - def get_aliases_from_distribution_id(self, distribution_id): - aliases = [] - try: - distributions = self.list_distributions(False) - for dist in distributions: - if dist['Id'] == distribution_id and 'Items' in dist['Aliases']: - for alias in dist['Aliases']['Items']: - aliases.append(alias) - break - return aliases - except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: - self.module.fail_json_aws(e, msg="Error getting list of aliases from distribution_id") - - def keyed_list_helper(self, list_to_key): - keyed_list = dict() - for item in list_to_key: - distribution_id = item['Id'] - if 'Items' in item['Aliases']: - aliases = item['Aliases']['Items'] - for alias in aliases: - keyed_list.update({alias: item}) - keyed_list.update({distribution_id: item}) - return keyed_list +from ansible_collections.amazon.aws.plugins.module_utils.cloudfront_facts import CloudFrontFactsServiceManager def set_facts_for_distribution_id_and_alias(details, facts, distribution_id, aliases): - facts[distribution_id].update(details) + facts[distribution_id] = details # also have a fixed key for accessing results/details returned facts['result'] = details facts['result']['DistributionId'] = distribution_id for alias in aliases: - facts[alias].update(details) + facts[alias] = details return facts @@ -530,7 +284,7 @@ def main(): module = AnsibleAWSModule(argument_spec=argument_spec, supports_check_mode=True) - service_mgr = CloudFrontServiceManager(module) + service_mgr = CloudFrontFactsServiceManager(module) distribution_id = module.params.get('distribution_id') invalidation_id = module.params.get('invalidation_id') @@ -582,55 +336,47 @@ def main(): module.fail_json(msg='Error unable to source a distribution id from domain_name_alias') # set appropriate cloudfront id - if distribution_id and not list_invalidations: - facts = {distribution_id: {}} - aliases = service_mgr.get_aliases_from_distribution_id(distribution_id) - for alias in aliases: - facts.update({alias: {}}) - if invalidation_id: - facts.update({invalidation_id: {}}) - elif distribution_id and list_invalidations: - facts = {distribution_id: {}} - aliases = service_mgr.get_aliases_from_distribution_id(distribution_id) - for alias in aliases: - facts.update({alias: {}}) - elif origin_access_identity_id: - facts = {origin_access_identity_id: {}} - elif web_acl_id: - facts = {web_acl_id: {}} + if invalidation_id is not None and invalidation: + facts.update({invalidation_id: {}}) + if origin_access_identity_id and (origin_access_identity or origin_access_identity_config): + facts.update({origin_access_identity_id: {}}) + if web_acl_id: + facts.update({web_acl_id: {}}) # get details based on options if distribution: - facts_to_set = service_mgr.get_distribution(distribution_id) + facts_to_set = service_mgr.get_distribution(id=distribution_id) if distribution_config: - facts_to_set = service_mgr.get_distribution_config(distribution_id) + facts_to_set = service_mgr.get_distribution_config(id=distribution_id) if origin_access_identity: - facts[origin_access_identity_id].update(service_mgr.get_origin_access_identity(origin_access_identity_id)) + facts[origin_access_identity_id].update(service_mgr.get_origin_access_identity(id=origin_access_identity_id)) if origin_access_identity_config: - facts[origin_access_identity_id].update(service_mgr.get_origin_access_identity_config(origin_access_identity_id)) + facts[origin_access_identity_id].update(service_mgr.get_origin_access_identity_config(id=origin_access_identity_id)) if invalidation: - facts_to_set = service_mgr.get_invalidation(distribution_id, invalidation_id) + facts_to_set = service_mgr.get_invalidation(distribution_id=distribution_id, id=invalidation_id) facts[invalidation_id].update(facts_to_set) if streaming_distribution: - facts_to_set = service_mgr.get_streaming_distribution(distribution_id) + facts_to_set = service_mgr.get_streaming_distribution(id=distribution_id) if streaming_distribution_config: - facts_to_set = service_mgr.get_streaming_distribution_config(distribution_id) + facts_to_set = service_mgr.get_streaming_distribution_config(id=distribution_id) if list_invalidations: - facts_to_set = {'invalidations': service_mgr.list_invalidations(distribution_id)} + invalidations = service_mgr.list_invalidations(distribution_id=distribution_id) or {} + facts_to_set = {'invalidations': invalidations} if 'facts_to_set' in vars(): + aliases = service_mgr.get_aliases_from_distribution_id(distribution_id) facts = set_facts_for_distribution_id_and_alias(facts_to_set, facts, distribution_id, aliases) # get list based on options if all_lists or list_origin_access_identities: - facts['origin_access_identities'] = service_mgr.list_origin_access_identities() + facts['origin_access_identities'] = service_mgr.list_origin_access_identities() or {} if all_lists or list_distributions: - facts['distributions'] = service_mgr.list_distributions() + facts['distributions'] = service_mgr.list_distributions() or {} if all_lists or list_streaming_distributions: - facts['streaming_distributions'] = service_mgr.list_streaming_distributions() + facts['streaming_distributions'] = service_mgr.list_streaming_distributions() or {} if list_distributions_by_web_acl_id: - facts['distributions_by_web_acl_id'] = service_mgr.list_distributions_by_web_acl_id(web_acl_id) + facts['distributions_by_web_acl_id'] = service_mgr.list_distributions_by_web_acl_id(web_acl_id=web_acl_id) or {} if list_invalidations: - facts['invalidations'] = service_mgr.list_invalidations(distribution_id) + facts['invalidations'] = service_mgr.list_invalidations(distribution_id=distribution_id) or {} # default summary option if summary: diff --git a/cloudfront_invalidation.py b/cloudfront_invalidation.py index b99a56c530e..dbf478e4408 100644 --- a/cloudfront_invalidation.py +++ b/cloudfront_invalidation.py @@ -152,9 +152,10 @@ class CloudFrontInvalidationServiceManager(object): Handles CloudFront service calls to AWS for invalidations """ - def __init__(self, module): + def __init__(self, module, cloudfront_facts_mgr): self.module = module self.client = module.client('cloudfront') + self.__cloudfront_facts_mgr = cloudfront_facts_mgr def create_invalidation(self, distribution_id, invalidation_batch): current_invalidation_response = self.get_invalidation(distribution_id, invalidation_batch['CallerReference']) @@ -174,28 +175,16 @@ def create_invalidation(self, distribution_id, invalidation_batch): self.module.fail_json_aws(e, msg="Error creating CloudFront invalidations.") def get_invalidation(self, distribution_id, caller_reference): - current_invalidation = {} # find all invalidations for the distribution - try: - paginator = self.client.get_paginator('list_invalidations') - invalidations = paginator.paginate(DistributionId=distribution_id).build_full_result().get('InvalidationList', {}).get('Items', []) - invalidation_ids = [inv['Id'] for inv in invalidations] - except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: - self.module.fail_json_aws(e, msg="Error listing CloudFront invalidations.") + invalidations = self.__cloudfront_facts_mgr.list_invalidations(distribution_id=distribution_id) # check if there is an invalidation with the same caller reference - for inv_id in invalidation_ids: - try: - invalidation = self.client.get_invalidation(DistributionId=distribution_id, Id=inv_id)['Invalidation'] - caller_ref = invalidation.get('InvalidationBatch', {}).get('CallerReference') - except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: - self.module.fail_json_aws(e, msg="Error getting CloudFront invalidation {0}".format(inv_id)) - if caller_ref == caller_reference: - current_invalidation = invalidation - break - - current_invalidation.pop('ResponseMetadata', None) - return current_invalidation + for invalidation in invalidations: + invalidation_info = self.__cloudfront_facts_mgr.get_invalidation(distribution_id=distribution_id, id=invalidation['Id']) + if invalidation_info.get('InvalidationBatch', {}).get('CallerReference') == caller_reference: + invalidation_info.pop('ResponseMetadata', None) + return invalidation_info + return {} class CloudFrontInvalidationValidationManager(object): @@ -203,9 +192,9 @@ class CloudFrontInvalidationValidationManager(object): Manages CloudFront validations for invalidation batches """ - def __init__(self, module): + def __init__(self, module, cloudfront_facts_mgr): self.module = module - self.__cloudfront_facts_mgr = CloudFrontFactsServiceManager(module) + self.__cloudfront_facts_mgr = cloudfront_facts_mgr def validate_distribution_id(self, distribution_id, alias): try: @@ -248,8 +237,9 @@ def main(): module = AnsibleAWSModule(argument_spec=argument_spec, supports_check_mode=False, mutually_exclusive=[['distribution_id', 'alias']]) - validation_mgr = CloudFrontInvalidationValidationManager(module) - service_mgr = CloudFrontInvalidationServiceManager(module) + cloudfront_facts_mgr = CloudFrontFactsServiceManager(module) + validation_mgr = CloudFrontInvalidationValidationManager(module, cloudfront_facts_mgr) + service_mgr = CloudFrontInvalidationServiceManager(module, cloudfront_facts_mgr) caller_reference = module.params.get('caller_reference') distribution_id = module.params.get('distribution_id') diff --git a/cloudfront_origin_access_identity.py b/cloudfront_origin_access_identity.py index 2d9009a9b9b..e59c9439701 100644 --- a/cloudfront_origin_access_identity.py +++ b/cloudfront_origin_access_identity.py @@ -127,6 +127,7 @@ from ansible_collections.amazon.aws.plugins.module_utils.cloudfront_facts import CloudFrontFactsServiceManager from ansible_collections.community.aws.plugins.module_utils.modules import AnsibleCommunityAWSModule as AnsibleAWSModule +from ansible_collections.amazon.aws.plugins.module_utils.core import is_boto3_error_code class CloudFrontOriginAccessIdentityServiceManager(object): @@ -151,9 +152,10 @@ def create_origin_access_identity(self, caller_reference, comment): def delete_origin_access_identity(self, origin_access_identity_id, e_tag): try: - return self.client.delete_cloud_front_origin_access_identity(Id=origin_access_identity_id, IfMatch=e_tag) + result = self.client.delete_cloud_front_origin_access_identity(Id=origin_access_identity_id, IfMatch=e_tag) + return result, True except (ClientError, BotoCoreError) as e: - self.module.fail_json_aws(e, msg="Error updating Origin Access Identity.") + self.module.fail_json_aws(e, msg="Error deleting Origin Access Identity.") def update_origin_access_identity(self, caller_reference, comment, origin_access_identity_id, e_tag): changed = False @@ -194,34 +196,45 @@ def __init__(self, module): self.module = module self.__cloudfront_facts_mgr = CloudFrontFactsServiceManager(module) - def validate_etag_from_origin_access_identity_id(self, origin_access_identity_id): + def describe_origin_access_identity(self, origin_access_identity_id, fail_if_missing=True): try: - if origin_access_identity_id is None: - return - oai = self.__cloudfront_facts_mgr.get_origin_access_identity(origin_access_identity_id) - if oai is not None: - return oai.get('ETag') - except (ClientError, BotoCoreError) as e: + return self.__cloudfront_facts_mgr.get_origin_access_identity(id=origin_access_identity_id, fail_if_error=False) + except is_boto3_error_code('NoSuchCloudFrontOriginAccessIdentity') as e: # pylint: disable=duplicate-except + if fail_if_missing: + self.module.fail_json_aws(e, msg="Error getting etag from origin_access_identity.") + return {} + except (ClientError, BotoCoreError) as e: # pylint: disable=duplicate-except self.module.fail_json_aws(e, msg="Error getting etag from origin_access_identity.") + def validate_etag_from_origin_access_identity_id(self, origin_access_identity_id, fail_if_missing): + oai = self.describe_origin_access_identity(origin_access_identity_id, fail_if_missing) + if oai is not None: + return oai.get('ETag') + def validate_origin_access_identity_id_from_caller_reference( self, caller_reference): - try: - origin_access_identities = self.__cloudfront_facts_mgr.list_origin_access_identities() - origin_origin_access_identity_ids = [oai.get('Id') for oai in origin_access_identities] - for origin_access_identity_id in origin_origin_access_identity_ids: - oai_config = (self.__cloudfront_facts_mgr.get_origin_access_identity_config(origin_access_identity_id)) - temp_caller_reference = oai_config.get('CloudFrontOriginAccessIdentityConfig').get('CallerReference') - if temp_caller_reference == caller_reference: - return origin_access_identity_id - except (ClientError, BotoCoreError) as e: - self.module.fail_json_aws(e, msg="Error getting Origin Access Identity from caller_reference.") + origin_access_identities = self.__cloudfront_facts_mgr.list_origin_access_identities() + origin_origin_access_identity_ids = [oai.get('Id') for oai in origin_access_identities] + for origin_access_identity_id in origin_origin_access_identity_ids: + oai_config = (self.__cloudfront_facts_mgr.get_origin_access_identity_config(id=origin_access_identity_id)) + temp_caller_reference = oai_config.get('CloudFrontOriginAccessIdentityConfig').get('CallerReference') + if temp_caller_reference == caller_reference: + return origin_access_identity_id def validate_comment(self, comment): if comment is None: return "origin access identity created by Ansible with datetime " + datetime.datetime.now().strftime('%Y-%m-%dT%H:%M:%S.%f') return comment + def validate_caller_reference_from_origin_access_identity_id(self, origin_access_identity_id, caller_reference): + if caller_reference is None: + if origin_access_identity_id is None: + return datetime.datetime.now().strftime('%Y-%m-%dT%H:%M:%S.%f') + oai = self.describe_origin_access_identity(origin_access_identity_id, fail_if_missing=True) + origin_access_config = oai.get('CloudFrontOriginAccessIdentity', {}).get('CloudFrontOriginAccessIdentityConfig', {}) + return origin_access_config.get('CallerReference') + return caller_reference + def main(): argument_spec = dict( @@ -248,18 +261,21 @@ def main(): if origin_access_identity_id is None and caller_reference is not None: origin_access_identity_id = validation_mgr.validate_origin_access_identity_id_from_caller_reference(caller_reference) - e_tag = validation_mgr.validate_etag_from_origin_access_identity_id(origin_access_identity_id) - comment = validation_mgr.validate_comment(comment) - if state == 'present': - if origin_access_identity_id is not None and e_tag is not None: + comment = validation_mgr.validate_comment(comment) + caller_reference = validation_mgr.validate_caller_reference_from_origin_access_identity_id(origin_access_identity_id, caller_reference) + if origin_access_identity_id is not None: + e_tag = validation_mgr.validate_etag_from_origin_access_identity_id(origin_access_identity_id, True) + # update cloudfront origin access identity result, changed = service_mgr.update_origin_access_identity(caller_reference, comment, origin_access_identity_id, e_tag) else: + # create cloudfront origin access identity result = service_mgr.create_origin_access_identity(caller_reference, comment) changed = True - elif state == 'absent' and origin_access_identity_id is not None and e_tag is not None: - result = service_mgr.delete_origin_access_identity(origin_access_identity_id, e_tag) - changed = True + else: + e_tag = validation_mgr.validate_etag_from_origin_access_identity_id(origin_access_identity_id, False) + if e_tag: + result, changed = service_mgr.delete_origin_access_identity(origin_access_identity_id, e_tag) result.pop('ResponseMetadata', None)