From ce2f5d26abdf60f20c81b03e6fbca7ea3828705c Mon Sep 17 00:00:00 2001 From: Will Thames Date: Wed, 27 Sep 2017 02:47:24 +1000 Subject: [PATCH] Improve cloudwatchevent_rule exception handling (#30823) * Fix cloudwatchevent_rule exception handling Where it is currently present, this change fixes the exception handling. However, there are many places that it is lacking. Fixes #30806 * Add new exception handling for cloudwatchevent_rule Ensure all API calls are wrapped with exception handling * PEP8 tidy up * Remove unnecessary HAS_BOTO3 import and checks Tidy up documentation so that NO_QA can be removed --- .../cloud/amazon/cloudwatchevent_rule.py | 90 ++++++++++++------- test/sanity/pep8/legacy-files.txt | 1 - 2 files changed, 58 insertions(+), 33 deletions(-) diff --git a/lib/ansible/modules/cloud/amazon/cloudwatchevent_rule.py b/lib/ansible/modules/cloud/amazon/cloudwatchevent_rule.py index cc2ae97f372..bb16223524e 100644 --- a/lib/ansible/modules/cloud/amazon/cloudwatchevent_rule.py +++ b/lib/ansible/modules/cloud/amazon/cloudwatchevent_rule.py @@ -107,24 +107,27 @@ rule: description: CloudWatch Event rule data returned: success type: dict - sample: "{ 'arn': 'arn:aws:events:us-east-1:123456789012:rule/MyCronTask', 'description': 'Run my scheduled task', 'name': 'MyCronTask', 'schedule_expression': 'cron(0 20 * * ? *)', 'state': 'ENABLED' }" + sample: + arn: 'arn:aws:events:us-east-1:123456789012:rule/MyCronTask' + description: 'Run my scheduled task' + name: 'MyCronTask' + schedule_expression: 'cron(0 20 * * ? *)' + state: 'ENABLED' targets: description: CloudWatch Event target(s) assigned to the rule returned: success type: list sample: "[{ 'arn': 'arn:aws:lambda:us-east-1:123456789012:function:MyFunction', 'id': 'MyTargetId' }]" -''' # NOQA +''' try: - import boto3.exception - import botocore.exceptions + import botocore except ImportError: - # module_utils.ec2.HAS_BOTO3 will do the right thing - pass + pass # handled by AnsibleAWSModule -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.ec2 import (HAS_BOTO3, boto3_conn, camel_dict_to_snake_dict, - ec2_argument_spec, get_aws_connection_info) +from ansible.module_utils.aws.core import AnsibleAWSModule +from ansible.module_utils.ec2 import boto3_conn, camel_dict_to_snake_dict +from ansible.module_utils.ec2 import ec2_argument_spec, get_aws_connection_info class CloudWatchEventRule(object): @@ -137,6 +140,7 @@ class CloudWatchEventRule(object): self.event_pattern = event_pattern self.description = description self.role_arn = role_arn + self.module = module def describe(self): """Returns the existing details of the rule in AWS""" @@ -146,7 +150,9 @@ class CloudWatchEventRule(object): error_code = e.response.get('Error', {}).get('Code') if error_code == 'ResourceNotFoundException': return {} - raise + self.module.fail_json_aws(e, msg="Could not describe rule %s" % self.name) + except botocore.exceptions.BotoCoreError as e: + self.module.fail_json_aws(e, msg="Could not describe rule %s" % self.name) return self._snakify(rule_info) def put(self, enabled=True): @@ -163,26 +169,39 @@ class CloudWatchEventRule(object): request['Description'] = self.description if self.role_arn: request['RoleArn'] = self.role_arn - response = self.client.put_rule(**request) + try: + response = self.client.put_rule(**request) + except (botocore.exceptions.BotoCoreError, botocore.exceptions.ClientError) as e: + self.module.fail_json_aws(e, msg="Could not create/update rule %s" % self.name) self.changed = True return response def delete(self): """Deletes the rule in AWS""" self.remove_all_targets() - response = self.client.delete_rule(Name=self.name) + + try: + response = self.client.delete_rule(Name=self.name) + except (botocore.exceptions.BotoCoreError, botocore.exceptions.ClientError) as e: + self.module.fail_json_aws(e, msg="Could not delete rule %s" % self.name) self.changed = True return response def enable(self): """Enables the rule in AWS""" - response = self.client.enable_rule(Name=self.name) + try: + response = self.client.enable_rule(Name=self.name) + except (botocore.exceptions.BotoCoreError, botocore.exceptions.ClientError) as e: + self.module.fail_json_aws(e, msg="Could not enable rule %s" % self.name) self.changed = True return response def disable(self): """Disables the rule in AWS""" - response = self.client.disable_rule(Name=self.name) + try: + response = self.client.disable_rule(Name=self.name) + except (botocore.exceptions.BotoCoreError, botocore.exceptions.ClientError) as e: + self.module.fail_json_aws(e, msg="Could not disable rule %s" % self.name) self.changed = True return response @@ -194,7 +213,9 @@ class CloudWatchEventRule(object): error_code = e.response.get('Error', {}).get('Code') if error_code == 'ResourceNotFoundException': return [] - raise + self.module.fail_json_aws(e, msg="Could not find target for rule %s" % self.name) + except botocore.exceptions.BotoCoreError as e: + self.module.fail_json_aws(e, msg="Could not find target for rule %s" % self.name) return self._snakify(targets)['targets'] def put_targets(self, targets): @@ -205,7 +226,10 @@ class CloudWatchEventRule(object): 'Rule': self.name, 'Targets': self._targets_request(targets), } - response = self.client.put_targets(**request) + try: + response = self.client.put_targets(**request) + except (botocore.exceptions.BotoCoreError, botocore.exceptions.ClientError) as e: + self.module.fail_json_aws(e, msg="Could not create/update rule targets for rule %s" % self.name) self.changed = True return response @@ -217,7 +241,10 @@ class CloudWatchEventRule(object): 'Rule': self.name, 'Ids': target_ids } - response = self.client.remove_targets(**request) + try: + response = self.client.remove_targets(**request) + except (botocore.exceptions.BotoCoreError, botocore.exceptions.ClientError) as e: + self.module.fail_json_aws(e, msg="Could not remove rule targets from rule %s" % self.name) self.changed = True return response @@ -379,26 +406,25 @@ def get_cloudwatchevents_client(module): resource='events', region=region, endpoint=ec2_url, **aws_conn_kwargs) - except boto3.exception.NoAuthHandlerFound as e: + except botocore.exceptions.ProfileNotFound as e: module.fail_json(msg=str(e)) def main(): argument_spec = ec2_argument_spec() - argument_spec.update(dict( - name = dict(required=True), - schedule_expression = dict(), - event_pattern = dict(), - state = dict(choices=['present', 'disabled', 'absent'], - default='present'), - description = dict(), - role_arn = dict(), - targets = dict(type='list', default=[]), - )) - module = AnsibleModule(argument_spec=argument_spec) - - if not HAS_BOTO3: - module.fail_json(msg='boto3 required for this module') + argument_spec.update( + dict( + name=dict(required=True), + schedule_expression=dict(), + event_pattern=dict(), + state=dict(choices=['present', 'disabled', 'absent'], + default='present'), + description=dict(), + role_arn=dict(), + targets=dict(type='list', default=[]), + ) + ) + module = AnsibleAWSModule(argument_spec=argument_spec) rule_data = dict( [(rf, module.params.get(rf)) for rf in CloudWatchEventRuleManager.RULE_FIELDS] diff --git a/test/sanity/pep8/legacy-files.txt b/test/sanity/pep8/legacy-files.txt index 0cce28707d0..42a3b64c010 100644 --- a/test/sanity/pep8/legacy-files.txt +++ b/test/sanity/pep8/legacy-files.txt @@ -14,7 +14,6 @@ lib/ansible/modules/cloud/amazon/aws_kms.py lib/ansible/modules/cloud/amazon/cloudformation.py lib/ansible/modules/cloud/amazon/cloudformation_facts.py lib/ansible/modules/cloud/amazon/cloudfront_facts.py -lib/ansible/modules/cloud/amazon/cloudwatchevent_rule.py lib/ansible/modules/cloud/amazon/dynamodb_table.py lib/ansible/modules/cloud/amazon/ec2_ami_copy.py lib/ansible/modules/cloud/amazon/ec2_ami_find.py