1""" 2Connection module for Amazon SQS 3 4.. versionadded:: 2014.7.0 5 6:configuration: This module accepts explicit sqs credentials but can also utilize 7 IAM roles assigned to the instance through Instance Profiles. Dynamic 8 credentials are then automatically obtained from AWS API and no further 9 configuration is necessary. More information available at: 10 11 .. code-block:: text 12 13 http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/iam-roles-for-amazon-ec2.html 14 15 If IAM roles are not used you need to specify them either in a pillar or 16 in the minion's config file: 17 18 .. code-block:: yaml 19 20 sqs.keyid: GKTADJGHEIQSXMKKRBJ08H 21 sqs.key: askdjghsdfjkghWupUjasdflkdfklgjsdfjajkghs 22 23 A region may also be specified in the configuration: 24 25 .. code-block:: yaml 26 27 sqs.region: us-east-1 28 29 If a region is not specified, the default is us-east-1. 30 31 It's also possible to specify key, keyid and region via a profile, either 32 as a passed in dict, or as a string to pull from pillars or minion config: 33 34 .. code-block:: yaml 35 36 myprofile: 37 keyid: GKTADJGHEIQSXMKKRBJ08H 38 key: askdjghsdfjkghWupUjasdflkdfklgjsdfjajkghs 39 region: us-east-1 40 41:depends: boto3 42""" 43# keep lint from choking on _get_conn and _cache_id 44# pylint: disable=E0602 45 46 47import logging 48import urllib.parse 49 50import salt.utils.json 51import salt.utils.versions 52 53log = logging.getLogger(__name__) 54 55__func_alias__ = { 56 "list_": "list", 57} 58 59try: 60 # pylint: disable=unused-import 61 import boto3 62 import botocore 63 64 # pylint: enable=unused-import 65 logging.getLogger("boto3").setLevel(logging.CRITICAL) 66 HAS_BOTO3 = True 67except ImportError: 68 HAS_BOTO3 = False 69 70 71def __virtual__(): 72 """ 73 Only load if boto3 libraries exist. 74 """ 75 has_boto_reqs = salt.utils.versions.check_boto_reqs() 76 if has_boto_reqs is True: 77 __utils__["boto3.assign_funcs"](__name__, "sqs") 78 return has_boto_reqs 79 80 81def _preprocess_attributes(attributes): 82 """ 83 Pre-process incoming queue attributes before setting them 84 """ 85 if isinstance(attributes, str): 86 attributes = salt.utils.json.loads(attributes) 87 88 def stringified(val): 89 # Some attributes take full json policy documents, but they take them 90 # as json strings. Convert the value back into a json string. 91 if isinstance(val, dict): 92 return salt.utils.json.dumps(val) 93 return val 94 95 return {attr: stringified(val) for attr, val in attributes.items()} 96 97 98def exists(name, region=None, key=None, keyid=None, profile=None): 99 """ 100 Check to see if a queue exists. 101 102 CLI Example: 103 104 .. code-block:: bash 105 106 salt myminion boto_sqs.exists myqueue region=us-east-1 107 """ 108 conn = _get_conn(region=region, key=key, keyid=keyid, profile=profile) 109 110 try: 111 conn.get_queue_url(QueueName=name) 112 except botocore.exceptions.ClientError as e: 113 missing_code = "AWS.SimpleQueueService.NonExistentQueue" 114 if e.response.get("Error", {}).get("Code") == missing_code: 115 return {"result": False} 116 return {"error": __utils__["boto3.get_error"](e)} 117 return {"result": True} 118 119 120def create( 121 name, 122 attributes=None, 123 region=None, 124 key=None, 125 keyid=None, 126 profile=None, 127): 128 """ 129 Create an SQS queue. 130 131 CLI Example: 132 133 .. code-block:: bash 134 135 salt myminion boto_sqs.create myqueue region=us-east-1 136 """ 137 conn = _get_conn(region=region, key=key, keyid=keyid, profile=profile) 138 139 if attributes is None: 140 attributes = {} 141 attributes = _preprocess_attributes(attributes) 142 143 try: 144 conn.create_queue(QueueName=name, Attributes=attributes) 145 except botocore.exceptions.ClientError as e: 146 return {"error": __utils__["boto3.get_error"](e)} 147 return {"result": True} 148 149 150def delete(name, region=None, key=None, keyid=None, profile=None): 151 """ 152 Delete an SQS queue. 153 154 CLI Example: 155 156 .. code-block:: bash 157 158 salt myminion boto_sqs.delete myqueue region=us-east-1 159 """ 160 conn = _get_conn(region=region, key=key, keyid=keyid, profile=profile) 161 162 try: 163 url = conn.get_queue_url(QueueName=name)["QueueUrl"] 164 conn.delete_queue(QueueUrl=url) 165 except botocore.exceptions.ClientError as e: 166 return {"error": __utils__["boto3.get_error"](e)} 167 return {"result": True} 168 169 170def list_(prefix="", region=None, key=None, keyid=None, profile=None): 171 """ 172 Return a list of the names of all visible queues. 173 174 .. versionadded:: 2016.11.0 175 176 CLI Example: 177 178 .. code-block:: bash 179 180 salt myminion boto_sqs.list region=us-east-1 181 """ 182 conn = _get_conn(region=region, key=key, keyid=keyid, profile=profile) 183 184 def extract_name(queue_url): 185 # Note: this logic taken from boto, so should be safe 186 return urllib.parse.urlparse(queue_url).path.split("/")[2] 187 188 try: 189 r = conn.list_queues(QueueNamePrefix=prefix) 190 # The 'QueueUrls' attribute is missing if there are no queues 191 urls = r.get("QueueUrls", []) 192 return {"result": [extract_name(url) for url in urls]} 193 except botocore.exceptions.ClientError as e: 194 return {"error": __utils__["boto3.get_error"](e)} 195 196 197def get_attributes(name, region=None, key=None, keyid=None, profile=None): 198 """ 199 Return attributes currently set on an SQS queue. 200 201 CLI Example: 202 203 .. code-block:: bash 204 205 salt myminion boto_sqs.get_attributes myqueue 206 """ 207 conn = _get_conn(region=region, key=key, keyid=keyid, profile=profile) 208 209 try: 210 url = conn.get_queue_url(QueueName=name)["QueueUrl"] 211 r = conn.get_queue_attributes(QueueUrl=url, AttributeNames=["All"]) 212 return {"result": r["Attributes"]} 213 except botocore.exceptions.ClientError as e: 214 return {"error": __utils__["boto3.get_error"](e)} 215 216 217def set_attributes( 218 name, 219 attributes, 220 region=None, 221 key=None, 222 keyid=None, 223 profile=None, 224): 225 """ 226 Set attributes on an SQS queue. 227 228 CLI Example: 229 230 .. code-block:: bash 231 232 salt myminion boto_sqs.set_attributes myqueue '{ReceiveMessageWaitTimeSeconds: 20}' region=us-east-1 233 """ 234 conn = _get_conn(region=region, key=key, keyid=keyid, profile=profile) 235 236 attributes = _preprocess_attributes(attributes) 237 238 try: 239 url = conn.get_queue_url(QueueName=name)["QueueUrl"] 240 conn.set_queue_attributes(QueueUrl=url, Attributes=attributes) 241 except botocore.exceptions.ClientError as e: 242 return {"error": __utils__["boto3.get_error"](e)} 243 return {"result": True} 244