1#!/usr/bin/python 2# Copyright: Ansible Project 3# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 5from __future__ import absolute_import, division, print_function 6__metaclass__ = type 7 8 9ANSIBLE_METADATA = {'metadata_version': '1.1', 10 'status': ['stableinterface'], 11 'supported_by': 'community'} 12 13 14DOCUMENTATION = """ 15--- 16module: sqs_queue 17short_description: Creates or deletes AWS SQS queues. 18description: 19 - Create or delete AWS SQS queues. 20 - Update attributes on existing queues. 21version_added: "2.0" 22author: 23 - Alan Loi (@loia) 24 - Fernando Jose Pando (@nand0p) 25 - Nadir Lloret (@nadirollo) 26requirements: 27 - "boto >= 2.33.0" 28options: 29 state: 30 description: 31 - Create or delete the queue 32 required: false 33 choices: ['present', 'absent'] 34 default: 'present' 35 name: 36 description: 37 - Name of the queue. 38 required: true 39 default_visibility_timeout: 40 description: 41 - The default visibility timeout in seconds. 42 message_retention_period: 43 description: 44 - The message retention period in seconds. 45 maximum_message_size: 46 description: 47 - The maximum message size in bytes. 48 delivery_delay: 49 description: 50 - The delivery delay in seconds. 51 receive_message_wait_time: 52 description: 53 - The receive message wait time in seconds. 54 policy: 55 description: 56 - The json dict policy to attach to queue 57 version_added: "2.1" 58 redrive_policy: 59 description: 60 - json dict with the redrive_policy (see example) 61 version_added: "2.2" 62extends_documentation_fragment: 63 - aws 64 - ec2 65""" 66 67RETURN = ''' 68default_visibility_timeout: 69 description: The default visibility timeout in seconds. 70 type: int 71 returned: always 72 sample: 30 73delivery_delay: 74 description: The delivery delay in seconds. 75 type: int 76 returned: always 77 sample: 0 78maximum_message_size: 79 description: The maximum message size in bytes. 80 type: int 81 returned: always 82 sample: 262144 83message_retention_period: 84 description: The message retention period in seconds. 85 type: int 86 returned: always 87 sample: 345600 88name: 89 description: Name of the SQS Queue 90 type: str 91 returned: always 92 sample: "queuename-987d2de0" 93queue_arn: 94 description: The queue's Amazon resource name (ARN). 95 type: str 96 returned: on successful creation or update of the queue 97 sample: 'arn:aws:sqs:us-east-1:199999999999:queuename-987d2de0' 98receive_message_wait_time: 99 description: The receive message wait time in seconds. 100 type: int 101 returned: always 102 sample: 0 103region: 104 description: Region that the queue was created within 105 type: str 106 returned: always 107 sample: 'us-east-1' 108''' 109 110EXAMPLES = ''' 111# Create SQS queue with redrive policy 112- sqs_queue: 113 name: my-queue 114 region: ap-southeast-2 115 default_visibility_timeout: 120 116 message_retention_period: 86400 117 maximum_message_size: 1024 118 delivery_delay: 30 119 receive_message_wait_time: 20 120 policy: "{{ json_dict }}" 121 redrive_policy: 122 maxReceiveCount: 5 123 deadLetterTargetArn: arn:aws:sqs:eu-west-1:123456789012:my-dead-queue 124 125# Delete SQS queue 126- sqs_queue: 127 name: my-queue 128 region: ap-southeast-2 129 state: absent 130''' 131 132import json 133import traceback 134 135try: 136 import boto.sqs 137 from boto.exception import BotoServerError, NoAuthHandlerFound 138 HAS_BOTO = True 139 140except ImportError: 141 HAS_BOTO = False 142 143from ansible.module_utils.basic import AnsibleModule 144from ansible.module_utils.ec2 import AnsibleAWSError, connect_to_aws, ec2_argument_spec, get_aws_connection_info 145 146 147def create_or_update_sqs_queue(connection, module): 148 queue_name = module.params.get('name') 149 150 queue_attributes = dict( 151 default_visibility_timeout=module.params.get('default_visibility_timeout'), 152 message_retention_period=module.params.get('message_retention_period'), 153 maximum_message_size=module.params.get('maximum_message_size'), 154 delivery_delay=module.params.get('delivery_delay'), 155 receive_message_wait_time=module.params.get('receive_message_wait_time'), 156 policy=module.params.get('policy'), 157 redrive_policy=module.params.get('redrive_policy') 158 ) 159 160 result = dict( 161 region=module.params.get('region'), 162 name=queue_name, 163 ) 164 result.update(queue_attributes) 165 166 try: 167 queue = connection.get_queue(queue_name) 168 if queue: 169 # Update existing 170 result['changed'] = update_sqs_queue(queue, check_mode=module.check_mode, **queue_attributes) 171 else: 172 # Create new 173 if not module.check_mode: 174 queue = connection.create_queue(queue_name) 175 update_sqs_queue(queue, **queue_attributes) 176 result['changed'] = True 177 178 if not module.check_mode: 179 result['queue_arn'] = queue.get_attributes('QueueArn')['QueueArn'] 180 result['default_visibility_timeout'] = queue.get_attributes('VisibilityTimeout')['VisibilityTimeout'] 181 result['message_retention_period'] = queue.get_attributes('MessageRetentionPeriod')['MessageRetentionPeriod'] 182 result['maximum_message_size'] = queue.get_attributes('MaximumMessageSize')['MaximumMessageSize'] 183 result['delivery_delay'] = queue.get_attributes('DelaySeconds')['DelaySeconds'] 184 result['receive_message_wait_time'] = queue.get_attributes('ReceiveMessageWaitTimeSeconds')['ReceiveMessageWaitTimeSeconds'] 185 186 except BotoServerError: 187 result['msg'] = 'Failed to create/update sqs queue due to error: ' + traceback.format_exc() 188 module.fail_json(**result) 189 else: 190 module.exit_json(**result) 191 192 193def update_sqs_queue(queue, 194 check_mode=False, 195 default_visibility_timeout=None, 196 message_retention_period=None, 197 maximum_message_size=None, 198 delivery_delay=None, 199 receive_message_wait_time=None, 200 policy=None, 201 redrive_policy=None): 202 changed = False 203 204 changed = set_queue_attribute(queue, 'VisibilityTimeout', default_visibility_timeout, 205 check_mode=check_mode) or changed 206 changed = set_queue_attribute(queue, 'MessageRetentionPeriod', message_retention_period, 207 check_mode=check_mode) or changed 208 changed = set_queue_attribute(queue, 'MaximumMessageSize', maximum_message_size, 209 check_mode=check_mode) or changed 210 changed = set_queue_attribute(queue, 'DelaySeconds', delivery_delay, 211 check_mode=check_mode) or changed 212 changed = set_queue_attribute(queue, 'ReceiveMessageWaitTimeSeconds', receive_message_wait_time, 213 check_mode=check_mode) or changed 214 changed = set_queue_attribute(queue, 'Policy', policy, 215 check_mode=check_mode) or changed 216 changed = set_queue_attribute(queue, 'RedrivePolicy', redrive_policy, 217 check_mode=check_mode) or changed 218 return changed 219 220 221def set_queue_attribute(queue, attribute, value, check_mode=False): 222 if not value and value != 0: 223 return False 224 225 try: 226 existing_value = queue.get_attributes(attributes=attribute)[attribute] 227 except Exception: 228 existing_value = '' 229 230 # convert dict attributes to JSON strings (sort keys for comparing) 231 if attribute in ['Policy', 'RedrivePolicy']: 232 value = json.dumps(value, sort_keys=True) 233 if existing_value: 234 existing_value = json.dumps(json.loads(existing_value), sort_keys=True) 235 236 if str(value) != existing_value: 237 if not check_mode: 238 queue.set_attribute(attribute, value) 239 return True 240 241 return False 242 243 244def delete_sqs_queue(connection, module): 245 queue_name = module.params.get('name') 246 247 result = dict( 248 region=module.params.get('region'), 249 name=queue_name, 250 ) 251 252 try: 253 queue = connection.get_queue(queue_name) 254 if queue: 255 if not module.check_mode: 256 connection.delete_queue(queue) 257 result['changed'] = True 258 259 else: 260 result['changed'] = False 261 262 except BotoServerError: 263 result['msg'] = 'Failed to delete sqs queue due to error: ' + traceback.format_exc() 264 module.fail_json(**result) 265 else: 266 module.exit_json(**result) 267 268 269def main(): 270 argument_spec = ec2_argument_spec() 271 argument_spec.update(dict( 272 state=dict(default='present', choices=['present', 'absent']), 273 name=dict(required=True, type='str'), 274 default_visibility_timeout=dict(type='int'), 275 message_retention_period=dict(type='int'), 276 maximum_message_size=dict(type='int'), 277 delivery_delay=dict(type='int'), 278 receive_message_wait_time=dict(type='int'), 279 policy=dict(type='dict', required=False), 280 redrive_policy=dict(type='dict', required=False), 281 )) 282 283 module = AnsibleModule( 284 argument_spec=argument_spec, 285 supports_check_mode=True) 286 287 if not HAS_BOTO: 288 module.fail_json(msg='boto required for this module') 289 290 region, ec2_url, aws_connect_params = get_aws_connection_info(module) 291 if not region: 292 module.fail_json(msg='region must be specified') 293 294 try: 295 connection = connect_to_aws(boto.sqs, region, **aws_connect_params) 296 297 except (NoAuthHandlerFound, AnsibleAWSError) as e: 298 module.fail_json(msg=str(e)) 299 300 state = module.params.get('state') 301 if state == 'present': 302 create_or_update_sqs_queue(connection, module) 303 elif state == 'absent': 304 delete_sqs_queue(connection, module) 305 306 307if __name__ == '__main__': 308 main() 309