99"""
1010
1111import logging
12+ import boto3
1213from botocore .exceptions import ClientError
1314
1415logger = logging .getLogger (__name__ )
@@ -26,6 +27,12 @@ def __init__(self, iot_client, iot_data_client=None):
2627 self .iot_client = iot_client
2728 self .iot_data_client = iot_data_client
2829
30+ @classmethod
31+ def from_client (cls ):
32+ iot_client = boto3 .client ("iot" )
33+ iot_data_client = boto3 .client ("iot-data" )
34+ return cls (iot_client , iot_data_client )
35+
2936 # snippet-end:[python.example_code.iot.IoTWrapper]
3037
3138 # snippet-start:[python.example_code.iot.CreateThing]
@@ -40,6 +47,9 @@ def create_thing(self, thing_name):
4047 response = self .iot_client .create_thing (thingName = thing_name )
4148 logger .info ("Created thing %s." , thing_name )
4249 except ClientError as err :
50+ if err .response ["Error" ]["Code" ] == "ResourceAlreadyExistsException" :
51+ logger .info ("Thing %s already exists. Skipping creation." , thing_name )
52+ return None
4353 logger .error (
4454 "Couldn't create thing %s. Here's why: %s: %s" ,
4555 thing_name ,
@@ -65,15 +75,18 @@ def list_things(self):
6575 for page in paginator .paginate ():
6676 things .extend (page ["things" ])
6777 logger .info ("Retrieved %s things." , len (things ))
78+ return things
6879 except ClientError as err :
69- logger .error (
70- "Couldn't list things. Here's why: %s: %s" ,
71- err .response ["Error" ]["Code" ],
72- err .response ["Error" ]["Message" ],
73- )
80+ if err .response ["Error" ]["Code" ] == "ThrottlingException" :
81+ logger .error ("Request throttled. Please try again later." )
82+ else :
83+ logger .error (
84+ "Couldn't list things. Here's why: %s: %s" ,
85+ err .response ["Error" ]["Code" ],
86+ err .response ["Error" ]["Message" ],
87+ )
7488 raise
75- else :
76- return things
89+
7790
7891 # snippet-end:[python.example_code.iot.ListThings]
7992
@@ -88,11 +101,14 @@ def create_keys_and_certificate(self):
88101 response = self .iot_client .create_keys_and_certificate (setAsActive = True )
89102 logger .info ("Created certificate %s." , response ["certificateId" ])
90103 except ClientError as err :
91- logger .error (
92- "Couldn't create keys and certificate. Here's why: %s: %s" ,
93- err .response ["Error" ]["Code" ],
94- err .response ["Error" ]["Message" ],
95- )
104+ if err .response ["Error" ]["Code" ] == "ThrottlingException" :
105+ logger .error ("Request throttled. Please try again later." )
106+ else :
107+ logger .error (
108+ "Couldn't create keys and certificate. Here's why: %s: %s" ,
109+ err .response ["Error" ]["Code" ],
110+ err .response ["Error" ]["Message" ],
111+ )
96112 raise
97113 else :
98114 return response
@@ -113,6 +129,9 @@ def attach_thing_principal(self, thing_name, principal):
113129 )
114130 logger .info ("Attached principal %s to thing %s." , principal , thing_name )
115131 except ClientError as err :
132+ if err .response ["Error" ]["Code" ] == "ResourceNotFoundException" :
133+ logger .error ("Cannot attach principal. Resource not found." )
134+ return
116135 logger .error (
117136 "Couldn't attach principal to thing. Here's why: %s: %s" ,
118137 err .response ["Error" ]["Code" ],
@@ -134,11 +153,14 @@ def describe_endpoint(self, endpoint_type="iot:Data-ATS"):
134153 response = self .iot_client .describe_endpoint (endpointType = endpoint_type )
135154 logger .info ("Retrieved endpoint %s." , response ["endpointAddress" ])
136155 except ClientError as err :
137- logger .error (
138- "Couldn't describe endpoint. Here's why: %s: %s" ,
139- err .response ["Error" ]["Code" ],
140- err .response ["Error" ]["Message" ],
141- )
156+ if err .response ["Error" ]["Code" ] == "ThrottlingException" :
157+ logger .error ("Request throttled. Please try again later." )
158+ else :
159+ logger .error (
160+ "Couldn't describe endpoint. Here's why: %s: %s" ,
161+ err .response ["Error" ]["Code" ],
162+ err .response ["Error" ]["Message" ],
163+ )
142164 raise
143165 else :
144166 return response ["endpointAddress" ]
@@ -158,15 +180,17 @@ def list_certificates(self):
158180 for page in paginator .paginate ():
159181 certificates .extend (page ["certificates" ])
160182 logger .info ("Retrieved %s certificates." , len (certificates ))
183+ return certificates
161184 except ClientError as err :
162- logger .error (
163- "Couldn't list certificates. Here's why: %s: %s" ,
164- err .response ["Error" ]["Code" ],
165- err .response ["Error" ]["Message" ],
166- )
185+ if err .response ["Error" ]["Code" ] == "ThrottlingException" :
186+ logger .error ("Request throttled. Please try again later." )
187+ else :
188+ logger .error (
189+ "Couldn't list certificates. Here's why: %s: %s" ,
190+ err .response ["Error" ]["Code" ],
191+ err .response ["Error" ]["Message" ],
192+ )
167193 raise
168- else :
169- return certificates
170194
171195 # snippet-end:[python.example_code.iot.ListCertificates]
172196
@@ -184,6 +208,9 @@ def detach_thing_principal(self, thing_name, principal):
184208 )
185209 logger .info ("Detached principal %s from thing %s." , principal , thing_name )
186210 except ClientError as err :
211+ if err .response ["Error" ]["Code" ] == "ResourceNotFoundException" :
212+ logger .error ("Cannot detach principal. Resource not found." )
213+ return
187214 logger .error (
188215 "Couldn't detach principal from thing. Here's why: %s: %s" ,
189216 err .response ["Error" ]["Code" ],
@@ -207,6 +234,9 @@ def delete_certificate(self, certificate_id):
207234 self .iot_client .delete_certificate (certificateId = certificate_id )
208235 logger .info ("Deleted certificate %s." , certificate_id )
209236 except ClientError as err :
237+ if err .response ["Error" ]["Code" ] == "ResourceNotFoundException" :
238+ logger .error ("Cannot delete certificate. Resource not found." )
239+ return
210240 logger .error (
211241 "Couldn't delete certificate. Here's why: %s: %s" ,
212242 err .response ["Error" ]["Code" ],
@@ -238,6 +268,9 @@ def create_topic_rule(self, rule_name, topic, sns_action_arn, role_arn):
238268 )
239269 logger .info ("Created topic rule %s." , rule_name )
240270 except ClientError as err :
271+ if err .response ["Error" ]["Code" ] == "ResourceAlreadyExistsException" :
272+ logger .info ("Topic rule %s already exists. Skipping creation." , rule_name )
273+ return
241274 logger .error (
242275 "Couldn't create topic rule. Here's why: %s: %s" ,
243276 err .response ["Error" ]["Code" ],
@@ -260,15 +293,18 @@ def list_topic_rules(self):
260293 for page in paginator .paginate ():
261294 rules .extend (page ["rules" ])
262295 logger .info ("Retrieved %s topic rules." , len (rules ))
296+ return rules
263297 except ClientError as err :
264- logger .error (
265- "Couldn't list topic rules. Here's why: %s: %s" ,
266- err .response ["Error" ]["Code" ],
267- err .response ["Error" ]["Message" ],
268- )
298+ if err .response ["Error" ]["Code" ] == "ThrottlingException" :
299+ logger .error ("Request throttled. Please try again later." )
300+ else :
301+ logger .error (
302+ "Couldn't list topic rules. Here's why: %s: %s" ,
303+ err .response ["Error" ]["Code" ],
304+ err .response ["Error" ]["Message" ],
305+ )
269306 raise
270- else :
271- return rules
307+
272308
273309 # snippet-end:[python.example_code.iot.ListTopicRules]
274310
@@ -284,11 +320,14 @@ def search_index(self, query):
284320 response = self .iot_client .search_index (queryString = query )
285321 logger .info ("Found %s things." , len (response .get ("things" , [])))
286322 except ClientError as err :
287- logger .error (
288- "Couldn't search index. Here's why: %s: %s" ,
289- err .response ["Error" ]["Code" ],
290- err .response ["Error" ]["Message" ],
291- )
323+ if err .response ["Error" ]["Code" ] == "ThrottlingException" :
324+ logger .error ("Request throttled. Please try again later." )
325+ else :
326+ logger .error (
327+ "Couldn't search index. Here's why: %s: %s" ,
328+ err .response ["Error" ]["Code" ],
329+ err .response ["Error" ]["Message" ],
330+ )
292331 raise
293332 else :
294333 return response .get ("things" , [])
@@ -326,6 +365,9 @@ def delete_thing(self, thing_name):
326365 self .iot_client .delete_thing (thingName = thing_name )
327366 logger .info ("Deleted thing %s." , thing_name )
328367 except ClientError as err :
368+ if err .response ["Error" ]["Code" ] == "ResourceNotFoundException" :
369+ logger .error ("Cannot delete thing. Resource not found." )
370+ return
329371 logger .error (
330372 "Couldn't delete thing. Here's why: %s: %s" ,
331373 err .response ["Error" ]["Code" ],
@@ -370,6 +412,9 @@ def update_thing_shadow(self, thing_name, shadow_state):
370412 )
371413 logger .info ("Updated shadow for thing %s." , thing_name )
372414 except ClientError as err :
415+ if err .response ["Error" ]["Code" ] == "ResourceNotFoundException" :
416+ logger .error ("Cannot update thing shadow. Resource not found." )
417+ return
373418 logger .error (
374419 "Couldn't update thing shadow. Here's why: %s: %s" ,
375420 err .response ["Error" ]["Code" ],
@@ -393,6 +438,9 @@ def get_thing_shadow(self, thing_name):
393438 shadow = json .loads (response ["payload" ].read ())
394439 logger .info ("Retrieved shadow for thing %s." , thing_name )
395440 except ClientError as err :
441+ if err .response ["Error" ]["Code" ] == "ResourceNotFoundException" :
442+ logger .error ("Cannot get thing shadow. Resource not found." )
443+ return None
396444 logger .error (
397445 "Couldn't get thing shadow. Here's why: %s: %s" ,
398446 err .response ["Error" ]["Code" ],
0 commit comments