diff options
author | Mark Chappell <mchappel@redhat.com> | 2020-02-27 23:26:20 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-02-27 15:26:20 -0700 |
commit | da30e6d2e1efa411b26e6a48e5d7f7cea644bbef (patch) | |
tree | ed59efbdb24a10e0122c7bc5487fbac1edc35bf8 | |
parent | 75b088d6a9882b9784a81cb27605d5ed7efed674 (diff) | |
download | ansible-da30e6d2e1efa411b26e6a48e5d7f7cea644bbef.tar.gz |
sqs_queue - Move to boto3 and add support for various extra features (#66795)
* reworked sqs_queue
* Switch default purge_tags behaviour to false.
This matches the behaviour of ec2_tag and ecs_tag.
* Minor lint / review fixups
* Add missing AWS IAM policy for SQS tests
* Move integration tests to using module_defaults: group/aws:...
* add changelog
* Break out the 'compatability' map from our spec definition (gets flagged by the schema validation)
* Tweaks based on review
* add basic examples
* Lint fixups
* Switch out NonExistentQueue logic so it's easier to follow
* Reorder name argument options for consistency
Co-authored-by: Dennis Podkovyrin <dennis.podkovyrin@gmail.com>
-rw-r--r-- | changelogs/fragments/66795-sqs_queue-boto3.yaml | 3 | ||||
-rw-r--r-- | hacking/aws_config/testing_policies/compute-policy.json | 14 | ||||
-rw-r--r-- | lib/ansible/modules/cloud/amazon/sqs_queue.py | 460 | ||||
-rw-r--r-- | test/integration/targets/sqs_queue/tasks/main.yml | 174 |
4 files changed, 411 insertions, 240 deletions
diff --git a/changelogs/fragments/66795-sqs_queue-boto3.yaml b/changelogs/fragments/66795-sqs_queue-boto3.yaml new file mode 100644 index 0000000000..ea05c63bda --- /dev/null +++ b/changelogs/fragments/66795-sqs_queue-boto3.yaml @@ -0,0 +1,3 @@ +minor_changes: +- 'sqs_queue: updated to use boto3 instead of boto' +- 'sqs_queue: Add support for tagging, KMS and FIFO queues' diff --git a/hacking/aws_config/testing_policies/compute-policy.json b/hacking/aws_config/testing_policies/compute-policy.json index a19b4256df..2d28aa41d3 100644 --- a/hacking/aws_config/testing_policies/compute-policy.json +++ b/hacking/aws_config/testing_policies/compute-policy.json @@ -263,6 +263,18 @@ "lightsail:StopInstance" ], "Resource": "arn:aws:lightsail:*:*:*" - } + }, + { + "Sid": "AllowSQS", + "Effect": "Allow", + "Action": [ + "sqs:GetQueueURL", + "sqs:CreateQueue", + "sqs:GetQueueAttributes", + "sqs:DeleteQueue", + "sqs:SetQueueAttributes" + ], + "Resource": "arn:aws:sqs:*:*:*" + }, ] } diff --git a/lib/ansible/modules/cloud/amazon/sqs_queue.py b/lib/ansible/modules/cloud/amazon/sqs_queue.py index a93d8d946f..6e8b680190 100644 --- a/lib/ansible/modules/cloud/amazon/sqs_queue.py +++ b/lib/ansible/modules/cloud/amazon/sqs_queue.py @@ -23,13 +23,13 @@ author: - Alan Loi (@loia) - Fernando Jose Pando (@nand0p) - Nadir Lloret (@nadirollo) + - Dennis Podkovyrin (@sbj-ss) requirements: - - "boto >= 2.33.0" + - boto3 options: state: description: - Create or delete the queue. - required: false choices: ['present', 'absent'] default: 'present' type: str @@ -38,9 +38,19 @@ options: - Name of the queue. required: true type: str - default_visibility_timeout: + queue_type: + description: + - Standard or FIFO queue. + - I(queue_type) can only be set at queue creation and will otherwise be + ignored. + choices: ['standard', 'fifo'] + default: 'standard' + version_added: "2.10" + type: str + visibility_timeout: description: - The default visibility timeout in seconds. + aliases: [default_visibility_timeout] type: int message_retention_period: description: @@ -50,13 +60,15 @@ options: description: - The maximum message size in bytes. type: int - delivery_delay: + delay_seconds: description: - The delivery delay in seconds. + aliases: [delivery_delay] type: int - receive_message_wait_time: + receive_message_wait_time_seconds: description: - The receive message wait time in seconds. + aliases: [receive_message_wait_time] type: int policy: description: @@ -68,22 +80,65 @@ options: - JSON dict with the redrive_policy (see example). version_added: "2.2" type: dict + kms_master_key_id: + description: + - The ID of an AWS-managed customer master key (CMK) for Amazon SQS or a custom CMK. + version_added: "2.10" + type: str + kms_data_key_reuse_period_seconds: + description: + - The length of time, in seconds, for which Amazon SQS can reuse a data key to encrypt or decrypt messages before calling AWS KMS again. + aliases: [kms_data_key_reuse_period] + version_added: "2.10" + type: int + content_based_deduplication: + type: bool + description: Enables content-based deduplication. Used for FIFOs only. + version_added: "2.10" + default: false + tags: + description: + - Tag dict to apply to the queue (requires botocore 1.5.40 or above). + - To remove all tags set I(tags={}) and I(purge_tags=true). + version_added: "2.10" + type: dict + purge_tags: + description: + - Remove tags not listed in I(tags). + type: bool + default: false + version_added: "2.10" extends_documentation_fragment: - aws - ec2 """ RETURN = ''' -default_visibility_timeout: +content_based_deduplication: + description: Enables content-based deduplication. Used for FIFOs only. + type: bool + returned: always + sample: True +visibility_timeout: description: The default visibility timeout in seconds. type: int returned: always sample: 30 -delivery_delay: +delay_seconds: description: The delivery delay in seconds. type: int returned: always sample: 0 +kms_master_key_id: + description: The ID of an AWS-managed customer master key (CMK) for Amazon SQS or a custom CMK. + type: str + returned: always + sample: alias/MyAlias +kms_data_key_reuse_period_seconds: + description: The length of time, in seconds, for which Amazon SQS can reuse a data key to encrypt or decrypt messages before calling AWS KMS again. + type: int + returned: always + sample: 300 maximum_message_size: description: The maximum message size in bytes. type: int @@ -102,9 +157,14 @@ name: queue_arn: description: The queue's Amazon resource name (ARN). type: str - returned: on successful creation or update of the queue + returned: on success sample: 'arn:aws:sqs:us-east-1:199999999999:queuename-987d2de0' -receive_message_wait_time: +queue_url: + description: URL to access the queue + type: str + returned: on success + sample: 'https://queue.amazonaws.com/123456789012/MyQueue' +receive_message_wait_time_seconds: description: The receive message wait time in seconds. type: int returned: always @@ -114,6 +174,11 @@ region: type: str returned: always sample: 'us-east-1' +tags: + description: List of queue tags + type: dict + returned: always + sample: '{"Env": "prod"}' ''' EXAMPLES = ''' @@ -131,6 +196,33 @@ EXAMPLES = ''' maxReceiveCount: 5 deadLetterTargetArn: arn:aws:sqs:eu-west-1:123456789012:my-dead-queue +# Drop redrive policy +- sqs_queue: + name: my-queue + region: ap-southeast-2 + redrive_policy: {} + +# Create FIFO queue +- sqs_queue: + name: fifo-queue + region: ap-southeast-2 + queue_type: fifo + content_based_deduplication: yes + +# Tag queue +- sqs_queue: + name: fifo-queue + region: ap-southeast-2 + tags: + example: SomeValue + +# Configure Encryption, automatically uses a new data key every hour +- sqs_queue: + name: fifo-queue + region: ap-southeast-2 + kms_master_key_id: alias/MyQueueKey + kms_data_key_reuse_period_seconds: 3600 + # Delete SQS queue - sqs_queue: name: my-queue @@ -139,178 +231,250 @@ EXAMPLES = ''' ''' import json -import traceback +from ansible.module_utils.aws.core import AnsibleAWSModule +from ansible.module_utils.ec2 import AWSRetry, camel_dict_to_snake_dict, compare_aws_tags, snake_dict_to_camel_dict, compare_policies try: - import boto.sqs - from boto.exception import BotoServerError, NoAuthHandlerFound - HAS_BOTO = True - + from botocore.exceptions import BotoCoreError, ClientError, ParamValidationError except ImportError: - HAS_BOTO = False - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.ec2 import AnsibleAWSError, connect_to_aws, ec2_argument_spec, get_aws_connection_info + pass # handled by AnsibleAWSModule -def create_or_update_sqs_queue(connection, module): - queue_name = module.params.get('name') +def get_queue_name(module, is_fifo=False): + name = module.params.get('name') + if not is_fifo or name.endswith('.fifo'): + return name + return name + '.fifo' - queue_attributes = dict( - default_visibility_timeout=module.params.get('default_visibility_timeout'), - message_retention_period=module.params.get('message_retention_period'), - maximum_message_size=module.params.get('maximum_message_size'), - delivery_delay=module.params.get('delivery_delay'), - receive_message_wait_time=module.params.get('receive_message_wait_time'), - policy=module.params.get('policy'), - redrive_policy=module.params.get('redrive_policy') - ) +# NonExistentQueue is explicitly expected when a queue doesn't exist +@AWSRetry.jittered_backoff() +def get_queue_url(client, name): + try: + return client.get_queue_url(QueueName=name)['QueueUrl'] + except ClientError as e: + if e.response['Error']['Code'] == 'AWS.SimpleQueueService.NonExistentQueue': + return None + raise + + +def describe_queue(client, queue_url): + """ + Description a queue in snake format + """ + attributes = client.get_queue_attributes(QueueUrl=queue_url, AttributeNames=['All'], aws_retry=True)['Attributes'] + description = dict(attributes) + description.pop('Policy', None) + description.pop('RedrivePolicy', None) + description = camel_dict_to_snake_dict(description) + description['policy'] = attributes.get('Policy', None) + description['redrive_policy'] = attributes.get('RedrivePolicy', None) + + # Boto3 returns everything as a string, convert them back to integers/dicts if + # that's what we expected. + for key, value in description.items(): + if value is None: + continue + + if key in ['policy', 'redrive_policy']: + policy = json.loads(value) + description[key] = policy + continue + + if key == 'content_based_deduplication': + try: + description[key] = bool(value) + except (TypeError, ValueError): + pass + + try: + if value == str(int(value)): + description[key] = int(value) + except (TypeError, ValueError): + pass + + return description + + +def create_or_update_sqs_queue(client, module): + is_fifo = (module.params.get('queue_type') == 'fifo') + queue_name = get_queue_name(module, is_fifo) result = dict( - region=module.params.get('region'), name=queue_name, + region=module.params.get('region'), + changed=False, ) - result.update(queue_attributes) - - try: - queue = connection.get_queue(queue_name) - if queue: - # Update existing - result['changed'] = update_sqs_queue(queue, check_mode=module.check_mode, **queue_attributes) - else: - # Create new - if not module.check_mode: - queue = connection.create_queue(queue_name) - update_sqs_queue(queue, **queue_attributes) - result['changed'] = True - - if not module.check_mode: - result['queue_arn'] = queue.get_attributes('QueueArn')['QueueArn'] - result['default_visibility_timeout'] = queue.get_attributes('VisibilityTimeout')['VisibilityTimeout'] - result['message_retention_period'] = queue.get_attributes('MessageRetentionPeriod')['MessageRetentionPeriod'] - result['maximum_message_size'] = queue.get_attributes('MaximumMessageSize')['MaximumMessageSize'] - result['delivery_delay'] = queue.get_attributes('DelaySeconds')['DelaySeconds'] - result['receive_message_wait_time'] = queue.get_attributes('ReceiveMessageWaitTimeSeconds')['ReceiveMessageWaitTimeSeconds'] - - except BotoServerError: - result['msg'] = 'Failed to create/update sqs queue due to error: ' + traceback.format_exc() - module.fail_json(**result) - else: - module.exit_json(**result) + queue_url = get_queue_url(client, queue_name) + result['queue_url'] = queue_url -def update_sqs_queue(queue, - check_mode=False, - default_visibility_timeout=None, - message_retention_period=None, - maximum_message_size=None, - delivery_delay=None, - receive_message_wait_time=None, - policy=None, - redrive_policy=None): - changed = False + if not queue_url: + create_attributes = {'FifoQueue': 'true'} if is_fifo else {} + result['changed'] = True + if module.check_mode: + return result + queue_url = client.create_queue(QueueName=queue_name, Attributes=create_attributes, aws_retry=True)['QueueUrl'] - changed = set_queue_attribute(queue, 'VisibilityTimeout', default_visibility_timeout, - check_mode=check_mode) or changed - changed = set_queue_attribute(queue, 'MessageRetentionPeriod', message_retention_period, - check_mode=check_mode) or changed - changed = set_queue_attribute(queue, 'MaximumMessageSize', maximum_message_size, - check_mode=check_mode) or changed - changed = set_queue_attribute(queue, 'DelaySeconds', delivery_delay, - check_mode=check_mode) or changed - changed = set_queue_attribute(queue, 'ReceiveMessageWaitTimeSeconds', receive_message_wait_time, - check_mode=check_mode) or changed - changed = set_queue_attribute(queue, 'Policy', policy, - check_mode=check_mode) or changed - changed = set_queue_attribute(queue, 'RedrivePolicy', redrive_policy, - check_mode=check_mode) or changed - return changed - - -def set_queue_attribute(queue, attribute, value, check_mode=False): - if not value and value != 0: - return False + changed, arn = update_sqs_queue(module, client, queue_url) + result['changed'] |= changed + result['queue_arn'] = arn - try: - existing_value = queue.get_attributes(attributes=attribute)[attribute] - except Exception: - existing_value = '' + changed, tags = update_tags(client, queue_url, module) + result['changed'] |= changed + result['tags'] = tags - # convert dict attributes to JSON strings (sort keys for comparing) - if attribute in ['Policy', 'RedrivePolicy']: - value = json.dumps(value, sort_keys=True) - if existing_value: - existing_value = json.dumps(json.loads(existing_value), sort_keys=True) + result.update(describe_queue(client, queue_url)) - if str(value) != existing_value: - if not check_mode: - queue.set_attribute(attribute, value) - return True + COMPATABILITY_KEYS = dict( + delay_seconds='delivery_delay', + receive_message_wait_time_seconds='receive_message_wait_time', + visibility_timeout='default_visibility_timeout', + kms_data_key_reuse_period_seconds='kms_data_key_reuse_period', + ) + for key in list(result.keys()): - return False + # The return values changed between boto and boto3, add the old keys too + # for backwards compatibility + return_name = COMPATABILITY_KEYS.get(key) + if return_name: + result[return_name] = result.get(key) + return result -def delete_sqs_queue(connection, module): - queue_name = module.params.get('name') +def update_sqs_queue(module, client, queue_url): + check_mode = module.check_mode + changed = False + existing_attributes = client.get_queue_attributes(QueueUrl=queue_url, AttributeNames=['All'], aws_retry=True)['Attributes'] + new_attributes = snake_dict_to_camel_dict(module.params, capitalize_first=True) + attributes_to_set = dict() + + # Boto3 SQS deals with policies as strings, we want to deal with them as + # dicts + if module.params.get('policy') is not None: + policy = module.params.get('policy') + current_value = existing_attributes.get('Policy', '{}') + current_policy = json.loads(current_value) + if compare_policies(current_policy, policy): + attributes_to_set['Policy'] = json.dumps(policy) + changed = True + if module.params.get('redrive_policy') is not None: + policy = module.params.get('redrive_policy') + current_value = existing_attributes.get('RedrivePolicy', '{}') + current_policy = json.loads(current_value) + if compare_policies(current_policy, policy): + attributes_to_set['RedrivePolicy'] = json.dumps(policy) + changed = True + + for attribute, value in existing_attributes.items(): + # We handle these as a special case because they're IAM policies + if attribute in ['Policy', 'RedrivePolicy']: + continue + + if attribute not in new_attributes.keys(): + continue + + if new_attributes.get(attribute) is None: + continue + + new_value = new_attributes[attribute] + + if isinstance(new_value, bool): + new_value = str(new_value).lower() + existing_value = str(existing_value).lower() + + if new_value == value: + continue + + # Boto3 expects strings + attributes_to_set[attribute] = str(new_value) + changed = True + + if changed and not check_mode: + client.set_queue_attributes(QueueUrl=queue_url, Attributes=attributes_to_set, aws_retry=True) + + return changed, existing_attributes.get('queue_arn'), + + +def delete_sqs_queue(client, module): + is_fifo = (module.params.get('queue_type') == 'fifo') + queue_name = get_queue_name(module, is_fifo) result = dict( - region=module.params.get('region'), name=queue_name, + region=module.params.get('region'), + changed=False ) - try: - queue = connection.get_queue(queue_name) - if queue: - if not module.check_mode: - connection.delete_queue(queue) - result['changed'] = True - - else: - result['changed'] = False - - except BotoServerError: - result['msg'] = 'Failed to delete sqs queue due to error: ' + traceback.format_exc() - module.fail_json(**result) - else: - module.exit_json(**result) - + queue_url = get_queue_url(client, queue_name) + if not queue_url: + return result -def main(): - argument_spec = ec2_argument_spec() - argument_spec.update(dict( - state=dict(default='present', choices=['present', 'absent']), - name=dict(required=True, type='str'), - default_visibility_timeout=dict(type='int'), - message_retention_period=dict(type='int'), - maximum_message_size=dict(type='int'), - delivery_delay=dict(type='int'), - receive_message_wait_time=dict(type='int'), - policy=dict(type='dict', required=False), - redrive_policy=dict(type='dict', required=False), - )) + result['changed'] = bool(queue_url) + if not module.check_mode: + AWSRetry.jittered_backoff()(client.delete_queue)(QueueUrl=queue_url) - module = AnsibleModule( - argument_spec=argument_spec, - supports_check_mode=True) + return result - if not HAS_BOTO: - module.fail_json(msg='boto required for this module') - region, ec2_url, aws_connect_params = get_aws_connection_info(module) - if not region: - module.fail_json(msg='region must be specified') +def update_tags(client, queue_url, module): + new_tags = module.params.get('tags') + purge_tags = module.params.get('purge_tags') + if new_tags is None: + return False, {} try: - connection = connect_to_aws(boto.sqs, region, **aws_connect_params) + existing_tags = client.list_queue_tags(QueueUrl=queue_url, aws_retry=True)['Tags'] + except (ClientError, KeyError) as e: + existing_tags = {} + + tags_to_add, tags_to_remove = compare_aws_tags(existing_tags, new_tags, purge_tags=purge_tags) + + if not module.check_mode: + if tags_to_remove: + client.untag_queue(QueueUrl=queue_url, TagKeys=tags_to_remove, aws_retry=True) + if tags_to_add: + client.tag_queue(QueueUrl=queue_url, Tags=tags_to_add) + existing_tags = client.list_queue_tags(QueueUrl=queue_url, aws_retry=True).get('Tags', {}) + else: + existing_tags = new_tags + + changed = bool(tags_to_remove) or bool(tags_to_add) + return changed, existing_tags + - except (NoAuthHandlerFound, AnsibleAWSError) as e: - module.fail_json(msg=str(e)) +def main(): + + argument_spec = dict( + state=dict(type='str', default='present', choices=['present', 'absent']), + name=dict(type='str', required=True), + queue_type=dict(type='str', default='standard', choices=['standard', 'fifo']), + delay_seconds=dict(type='int', aliases=['delivery_delay']), + maximum_message_size=dict(type='int'), + message_retention_period=dict(type='int'), + policy=dict(type='dict'), + receive_message_wait_time_seconds=dict(type='int', aliases=['receive_message_wait_time']), + redrive_policy=dict(type='dict'), + visibility_timeout=dict(type='int', aliases=['default_visibility_timeout']), + kms_master_key_id=dict(type='str'), + kms_data_key_reuse_period_seconds=dict(type='int', aliases=['kms_data_key_reuse_period']), + content_based_deduplication=dict(type='bool'), + tags=dict(type='dict'), + purge_tags=dict(type='bool', default=False), + ) + module = AnsibleAWSModule(argument_spec=argument_spec, supports_check_mode=True) state = module.params.get('state') - if state == 'present': - create_or_update_sqs_queue(connection, module) - elif state == 'absent': - delete_sqs_queue(connection, module) + retry_decorator = AWSRetry.jittered_backoff(catch_extra_error_codes=['AWS.SimpleQueueService.NonExistentQueue']) + try: + client = module.client('sqs', retry_decorator=retry_decorator) + if state == 'present': + result = create_or_update_sqs_queue(client, module) + elif state == 'absent': + result = delete_sqs_queue(client, module) + except (BotoCoreError, ClientError, ParamValidationError) as e: + module.fail_json_aws(e, msg='Failed to control sqs queue') + else: + module.exit_json(**result) if __name__ == '__main__': diff --git a/test/integration/targets/sqs_queue/tasks/main.yml b/test/integration/targets/sqs_queue/tasks/main.yml index 71df889d7a..b689c9eb2b 100644 --- a/test/integration/targets/sqs_queue/tasks/main.yml +++ b/test/integration/targets/sqs_queue/tasks/main.yml @@ -1,114 +1,106 @@ --- -- name: set up aws connection info - set_fact: - aws_connection_info: &aws_connection_info +- name: Main test block + module_defaults: + group/aws: aws_access_key: "{{ aws_access_key }}" aws_secret_key: "{{ aws_secret_key }}" - security_token: "{{ security_token }}" + security_token: "{{ security_token | default(omit) }}" region: "{{ aws_region }}" - no_log: yes -- block: - - name: Test creating SQS queue - sqs_queue: - name: "{{ resource_prefix }}{{ 1000 | random }}" - <<: *aws_connection_info - register: create_result - - name: Assert SQS queue created - assert: - that: - - create_result.changed - - create_result.region == "{{ aws_region }}" - always: - - name: Test deleting SQS queue - sqs_queue: - name: "{{ create_result.name }}" - state: absent - <<: *aws_connection_info - register: delete_result - retries: 3 - delay: 3 - until: delete_result.changed - - name: Assert SQS queue deleted - assert: - that: - - delete_result.changed - - name: Test delete SQS queue that doesn't exist - sqs_queue: - name: "{{ resource_prefix }}{{ 1000 | random }}" - state: absent - <<: *aws_connection_info - register: delete_result - - name: Assert delete non-existant queue returns cleanly - assert: - that: - - delete_result.changed == False -- name: Test queue features block: - - name: Test create queue with attributes + - block: + - name: Test creating SQS queue sqs_queue: name: "{{ resource_prefix }}{{ 1000 | random }}" - default_visibility_timeout: 900 - delivery_delay: 900 - maximum_message_size: 9009 - message_retention_period: 900 - receive_message_wait_time: 10 - policy: - Version: "2012-10-17" - Statement: - Effect: Allow - Action: "*" - <<: *aws_connection_info register: create_result - - name: Assert queue created with configuration + - name: Assert SQS queue created assert: that: - create_result.changed - - create_result.default_visibility_timeout == "900" - - create_result.delivery_delay == "900" - - create_result.maximum_message_size == "9009" - - create_result.message_retention_period == "900" - - create_result.receive_message_wait_time == "10" - - create_result.policy.Version == "2012-10-17" - - create_result.policy.Statement.Effect == "Allow" - - create_result.policy.Statement.Action == "*" - always: - - name: Cleaning up queue + - create_result.region == "{{ aws_region }}" + always: + - name: Test deleting SQS queue sqs_queue: name: "{{ create_result.name }}" state: absent - <<: *aws_connection_info register: delete_result retries: 3 delay: 3 until: delete_result.changed -- name: Test queue with redrive - block: - - name: Creating dead letter queue - sqs_queue: - name: "{{ resource_prefix }}{{ 1000 | random }}" - <<: *aws_connection_info - register: dead_letter_queue - - name: Test create queue with redrive_policy - sqs_queue: - name: "{{ resource_prefix }}{{ 1000 | random }}" - redrive_policy: - maxReceiveCount: 5 - deadLetterTargetArn: "{{ dead_letter_queue.queue_arn }}" - <<: *aws_connection_info - register: create_result - - name: Assert queue created with configuration + - name: Assert SQS queue deleted assert: that: - - create_result.changed - always: - - name: Cleaning up queue + - delete_result.changed + - name: Test delete SQS queue that doesn't exist sqs_queue: - name: "{{ item.name }}" + name: "{{ resource_prefix }}{{ 1000 | random }}" state: absent - <<: *aws_connection_info register: delete_result - retries: 3 - delay: 3 - with_items: - - { name: "{{ create_result.name }}" } - - { name: "{{ dead_letter_queue.name }}" } + - name: Assert delete non-existant queue returns cleanly + assert: + that: + - delete_result.changed == False + - name: Test queue features + block: + - name: Test create queue with attributes + sqs_queue: + name: "{{ resource_prefix }}{{ 1000 | random }}" + default_visibility_timeout: 900 + delivery_delay: 900 + maximum_message_size: 9009 + message_retention_period: 900 + receive_message_wait_time: 10 + policy: + Version: "2012-10-17" + Statement: + Effect: Allow + Action: "*" + register: create_result + - name: Assert queue created with configuration + assert: + that: + - create_result.changed + - create_result.default_visibility_timeout == 900 + - create_result.delivery_delay == 900 + - create_result.maximum_message_size == 9009 + - create_result.message_retention_period == 900 + - create_result.receive_message_wait_time == 10 + - create_result.policy.Version == "2012-10-17" + - create_result.policy.Statement[0].Effect == "Allow" + - create_result.policy.Statement[0].Action == "*" + always: + - name: Cleaning up queue + sqs_queue: + name: "{{ create_result.name }}" + state: absent + register: delete_result + retries: 3 + delay: 3 + until: delete_result.changed + - name: Test queue with redrive + block: + - name: Creating dead letter queue + sqs_queue: + name: "{{ resource_prefix }}{{ 1000 | random }}" + register: dead_letter_queue + - name: Test create queue with redrive_policy + sqs_queue: + name: "{{ resource_prefix }}{{ 1000 | random }}" + redrive_policy: + maxReceiveCount: 5 + deadLetterTargetArn: "{{ dead_letter_queue.queue_arn }}" + register: create_result + - name: Assert queue created with configuration + assert: + that: + - create_result.changed + always: + - name: Cleaning up queue + sqs_queue: + name: "{{ item.name }}" + state: absent + register: delete_result + retries: 3 + delay: 3 + with_items: + - { name: "{{ create_result.name }}" } + - { name: "{{ dead_letter_queue.name }}" } |