gofannon 0.1.0__py3-none-any.whl → 0.25.11__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,666 @@
1
+ from typing import Type, Callable
2
+ import subprocess
3
+ import shutil
4
+ import zipfile
5
+ import json
6
+ import time
7
+
8
+ try:
9
+ import boto3
10
+ from botocore.exceptions import ClientError
11
+ from botocore.client import BaseClient
12
+
13
+ _HAS_BOTO3 = True
14
+ except ImportError:
15
+ _HAS_BOTO3 = False
16
+
17
+ try:
18
+ from jsonschema import validate
19
+ import jsonschema.exceptions
20
+
21
+ _HAS_JSONSCHEMA = True
22
+ except ImportError:
23
+ _HAS_JSONSCHEMA = False
24
+
25
+
26
+ class BedrockMixin:
27
+
28
+ def export_to_bedrock(self, agent_app_config: dict = None) -> dict:
29
+ """
30
+ Export tool as Bedrock Agent tool configuration
31
+ """
32
+ if not _HAS_BOTO3:
33
+ error = "boto3 not installed. Install with `pip install boto3`"
34
+ self.logger.error(error)
35
+ raise RuntimeError(error)
36
+
37
+ if not _HAS_JSONSCHEMA:
38
+ error = "jasonschema not installed. Install with `pip install jsonschema`"
39
+ self.logger.error(error)
40
+ raise RuntimeError(error)
41
+
42
+ valid_agent_app_config_schema = {
43
+ "type": "object",
44
+ "properties": {
45
+ "app_id": {"type": "string"},
46
+ "agent_session_timeout": {"type": "integer"},
47
+ "instruction": {"type": "string"},
48
+ "agent_description": {"type": "string"},
49
+ "target_model": {"type": "string"},
50
+ "python_runtime_version": {"type": "string"},
51
+ "temp_build_root": {"type": "string"},
52
+ },
53
+ "required": [
54
+ "app_id",
55
+ "agent_session_timeout",
56
+ "instruction",
57
+ "agent_description",
58
+ "target_model",
59
+ "python_runtime_version",
60
+ "temp_build_root",
61
+ ],
62
+ }
63
+ try:
64
+ validate(agent_app_config, valid_agent_app_config_schema)
65
+ except jsonschema.exceptions.ValidationError as err:
66
+ error = f"JSON validation failure on input parameters: {err}"
67
+ self.logger.error(error)
68
+ raise RuntimeError(error)
69
+
70
+ self.bedrock_agent_client = boto3.client("bedrock-agent")
71
+ self.app_id = agent_app_config["app_id"]
72
+ self.agent_name = agent_app_config["agent_name"]
73
+ self.agent_session_timeout = agent_app_config["agent_session_timeout"]
74
+ self.agent_instruction = agent_app_config["instruction"]
75
+ self.agent_description = agent_app_config["agent_description"]
76
+ self.agent_target_model = agent_app_config["target_model"]
77
+ self.python_runtime_version = agent_app_config["python_runtime_version"]
78
+ self.temp_build_root = agent_app_config["temp_build_root"]
79
+ try:
80
+ self.aws_account_id = (
81
+ boto3.client("sts").get_caller_identity().get("Account")
82
+ )
83
+ except ClientError as e:
84
+ error = f"Error getting AWS account number. Client error: {e}"
85
+ self.logger.error(error)
86
+ raise RuntimeError(error)
87
+ except Exception as e:
88
+ error = f"Error getting AWS account number. Unexpected error: {e}"
89
+ self.logger.error(error)
90
+ raise RuntimeError(error)
91
+
92
+ self.openapi_schema_dict = self._generate_openapi_schema()
93
+
94
+ self.logger.info(
95
+ f"Starting build of app {self.app_id}...", self.__class__.__name__
96
+ )
97
+ # Creates:
98
+ # the lambda - a .zip archive that contains all the dependencies and the lambda source.
99
+ # This lambda will have a resource-based policy attached giving it
100
+ # permission to be invoked by the agent attached.
101
+ # an IAM role - the lambda execution role with managed attached policy
102
+ # AWSLambdaBasicExecutionRole allowing the lambda to use CloudWatch
103
+
104
+ self.logger.info("\tCreating lambda...", self.__class__.__name__)
105
+
106
+ self.lambda_arn = self._create_bedrock_lambda()
107
+
108
+ # Creates:
109
+ # the Bedrock agent - The bedrock agent itself
110
+ # an IAM role - The agent execution role
111
+ # An IAM policy - a policy to attach to the role allowing the agent to invoke the
112
+ # - foundational model
113
+ self.logger.info("\tCreating agent...", self.__class__.__name__)
114
+ self.agent_id = self._create_bedrock_agent()
115
+
116
+ # Creates:
117
+ # the Bedrock agent action group - Defined with an API schema
118
+ self.logger.info("\tCreating agent action group...", self.__class__.__name__)
119
+ action_group = self._create_agent_action_group()
120
+
121
+ # Finally, prepare the agent
122
+ self.logger.info("\tPreparing agent...", self.__class__.__name__)
123
+ try:
124
+ response = self.bedrock_agent_client.prepare_agent(agentId=self.agent_id)
125
+ except ClientError as e:
126
+ error = f"Error preparing agent. Client error: {e}"
127
+ self.logger.error(error)
128
+ raise RuntimeError(error)
129
+ except Exception as e:
130
+ error = f"Error preparing agent. Unexpected error: {e}"
131
+ self.logger.error(error)
132
+ raise RuntimeError(error)
133
+
134
+ output_manifest = {
135
+ "lambdaARN": self.lambda_arn,
136
+ "lambdaRoleName": self.lambda_role_name,
137
+ "agentId": self.agent_id,
138
+ "agentRoleName": self.agent_role_name,
139
+ "agentPolicyARN": self.agent_role_policy_arn,
140
+ "agentActionGroup": self.agent_action_group_id,
141
+ }
142
+ self.logger.info("Done!", self.__class__.__name__)
143
+ return output_manifest
144
+
145
+ def _generate_openapi_schema(self) -> dict:
146
+ """Convert Gofannon definition to OpenAPI schema"""
147
+ params = self.definition["function"]["parameters"]
148
+ if not "properties" in params:
149
+ params["properties"] = {}
150
+ openapi_schema = {
151
+ "openapi": "3.0.0",
152
+ "info": {"title": self.name, "version": "1.0.0"},
153
+ "paths": {
154
+ f"/{self.name}": {
155
+ "get": {
156
+ "description": self.definition["function"]["description"],
157
+ "requestBody": {
158
+ "content": {
159
+ "application/json": {
160
+ "schema": {
161
+ "type": "object",
162
+ "properties": {
163
+ param: {
164
+ "type": props["type"],
165
+ "description": props["description"],
166
+ }
167
+ for param, props in params[
168
+ "properties"
169
+ ].items()
170
+ },
171
+ "required": params.get("required", []),
172
+ }
173
+ }
174
+ }
175
+ },
176
+ "responses": {
177
+ "200": {
178
+ "description": "Successful operation",
179
+ "content": {
180
+ "application/json": {
181
+ "schema": {
182
+ "type": "object",
183
+ "properties": {
184
+ "result": {"type": "string"}
185
+ },
186
+ }
187
+ }
188
+ },
189
+ }
190
+ },
191
+ }
192
+ }
193
+ },
194
+ }
195
+
196
+ return openapi_schema
197
+
198
+ def _create_bedrock_lambda(self) -> str:
199
+ """Create Lambda function for Bedrock integration"""
200
+
201
+ lambda_client = boto3.client("lambda")
202
+ self.lambda_role_arn = self._create_bedrock_lambda_role()
203
+
204
+ # Build the lambda .zip deployment package here. Package consits of:
205
+ # 1. All the Python dependencies, including Gofannon itself
206
+ # 2. The lambda source code.
207
+ # bash code as comments at the bottom of this file.
208
+ # See: https://docs.aws.amazon.com/lambda/latest/dg/python-package.html
209
+
210
+ # TODO: verify the path here
211
+ command = f"""../../scripts/build_lambda.sh {self.temp_build_root} {self.python_runtime_version.replace("python","")} {self.app_id}"""
212
+ try:
213
+ process = subprocess.Popen(
214
+ command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE
215
+ )
216
+ stdout, stderr = process.communicate()
217
+
218
+ if process.returncode == 0:
219
+ self.built_archive = stdout.decode("utf-8").replace("\n", "")
220
+ else:
221
+ raise RuntimeError(stderr.decode("utf-8"))
222
+
223
+ except Exception as e:
224
+ error = f"Error creating .zip archive. {e}"
225
+ self.logger.error(error)
226
+ raise RuntimeError(error)
227
+
228
+ # TODO: Skeleton code in the function directory or here?
229
+ lambda_src_string = self._get_lambda_source(
230
+ module_name=self.__class__.__module__, class_name=self.__class__.__name__
231
+ )
232
+
233
+ try:
234
+ with open(f"{self.temp_build_root}/lambda_function.py", "w") as text_file:
235
+ text_file.write(lambda_src_string)
236
+ except Exception as e:
237
+ error = f"Error writing lambda Python source file: {e}"
238
+ self.logger.error(error)
239
+ raise RuntimeError(error)
240
+
241
+ try:
242
+ with zipfile.ZipFile(
243
+ self.built_archive,
244
+ "a",
245
+ compression=zipfile.ZIP_DEFLATED,
246
+ ) as zipf:
247
+ zipf.write(
248
+ f"{self.temp_build_root}/lambda_function.py", "lambda_function.py"
249
+ )
250
+ except Exception as e:
251
+ error = f"Error inserting lambda Python source file into zip: {e}"
252
+ self.logger.error(error)
253
+ raise RuntimeError(error)
254
+
255
+ with open(self.built_archive, "rb") as f:
256
+ zipped_code = f.read()
257
+
258
+ try:
259
+ response = lambda_client.create_function(
260
+ FunctionName=f"{self.app_id}_{self.name}",
261
+ Runtime=self.python_runtime_version,
262
+ Role=self.lambda_role_arn,
263
+ Handler="lambda_function.lambda_handler",
264
+ Code={"ZipFile": zipped_code},
265
+ Description=f"{self.app_id} tool: {self.name}",
266
+ Timeout=30,
267
+ MemorySize=256,
268
+ )
269
+ except ClientError as e:
270
+ error = f"Error creating lambda. Client error: {e}"
271
+ self.logger.error(error)
272
+ raise RuntimeError(error)
273
+
274
+ except Exception as e:
275
+ error = f"Error creating lambda. Unexpected error: {e}"
276
+ self.logger.error(error)
277
+ raise RuntimeError(error)
278
+
279
+ # Clean up the .zip archive build
280
+ try:
281
+ shutil.rmtree(self.temp_build_root)
282
+ except OSError as e:
283
+ error = (
284
+ f"Error deleting temporary build directory {self.temp_build_root}: {e}"
285
+ )
286
+ self.logger.error(error)
287
+ pass
288
+
289
+ # Add the resourced-base policy allowing the lambda to be invoked
290
+ # by the agent.
291
+ try:
292
+ add_permission_response = lambda_client.add_permission(
293
+ StatementId=f"{self.app_id}-bedrock-invoke",
294
+ FunctionName=response["FunctionArn"],
295
+ Action="lambda:InvokeFunction",
296
+ Principal="bedrock.amazonaws.com",
297
+ # TODO: fix this. Remove wildcard
298
+ SourceArn=f"arn:aws:bedrock:us-east-1:{self.aws_account_id}:agent/*",
299
+ )
300
+ except ClientError as e:
301
+ error = f"Error attaching resource policy to lambda execution role. Client error: {e}"
302
+ self.logger.error(error)
303
+ raise RuntimeError(error)
304
+ except Exception as e:
305
+ error = f"Error attaching resource policy to lambda execution role. Unexpected error: {e}"
306
+ self.logger.error(error)
307
+ raise RuntimeError(error)
308
+
309
+ return response["FunctionArn"]
310
+
311
+ def _create_bedrock_lambda_role(self) -> str:
312
+ """Get or create IAM role for Bedrock integration"""
313
+ iam = boto3.client("iam")
314
+
315
+ self.lambda_role_name = f"{self.app_id}_bedrock_lambda_execution_role"
316
+ self.assume_role = self._get_assumed_role(service="lambda.amazonaws.com")
317
+
318
+ try:
319
+ iam.create_role(
320
+ RoleName=self.lambda_role_name,
321
+ AssumeRolePolicyDocument=json.dumps(self.assume_role),
322
+ )
323
+ except ClientError as e:
324
+ error = f"Error creating lambda execution role. Client error: {e}"
325
+ self.logger.error(error)
326
+ raise RuntimeError(error)
327
+ except Exception as e:
328
+ error = f"Error creating lambda execution role. Unexpected error: {e}"
329
+ self.logger.error(error)
330
+ raise RuntimeError(error)
331
+
332
+ try:
333
+ iam.attach_role_policy(
334
+ RoleName=self.lambda_role_name,
335
+ PolicyArn="arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole",
336
+ )
337
+ except ClientError as e:
338
+ error = f"Error attaching managed policy to lambda execution role. Client error: {e}"
339
+ self.logger.error(error)
340
+ raise RuntimeError(error)
341
+
342
+ except Exception as e:
343
+ error = f"Error attaching managed policy to lambda execution role. Unexpected error: {e}"
344
+ self.logger.error(error)
345
+ raise RuntimeError(error)
346
+
347
+ return iam.get_role(RoleName=self.lambda_role_name)["Role"]["Arn"]
348
+
349
+ def _create_bedrock_agent(self) -> str:
350
+ """Create Bedrock agent"""
351
+
352
+ self.agent_role_arn = self._create_agent_role()
353
+
354
+ args = {
355
+ "agentName": f"{self.app_id}_{self.agent_name}Agent",
356
+ "agentResourceRoleArn": self.agent_role_arn,
357
+ "foundationModel": self.agent_target_model,
358
+ "idleSessionTTLInSeconds": self.agent_session_timeout,
359
+ "instruction": self.agent_instruction,
360
+ "description": self.agent_description,
361
+ }
362
+
363
+ try:
364
+ response = self.bedrock_agent_client.create_agent(**args)
365
+ except ClientError as e:
366
+ error = f"Error creating agent. Client error: {e}"
367
+ self.logger.error(error)
368
+ raise RuntimeError(error)
369
+
370
+ except Exception as e:
371
+ error = f"Error creating agent. Unexpected error: {e}"
372
+ self.logger.error(error)
373
+ raise RuntimeError(error)
374
+
375
+ return response["agent"]["agentId"]
376
+
377
+ def _create_agent_action_group(self):
378
+ """Create Bedrock action group and attach to Bedrock agent"""
379
+
380
+ args = {
381
+ "agentId": self.agent_id,
382
+ "actionGroupExecutor": {
383
+ "lambda": self.lambda_arn,
384
+ },
385
+ "actionGroupName": f"{self.app_id}_{self.agent_name}_ag",
386
+ "agentVersion": "DRAFT",
387
+ "apiSchema": {"payload": json.dumps(self.openapi_schema_dict)},
388
+ "description": self.agent_description,
389
+ }
390
+
391
+ # Wait until agent status transitions to CREATING before creating the action group.
392
+ counter = 0
393
+ agent_details = self.bedrock_agent_client.get_agent(agentId=self.agent_id)
394
+ agent_status = agent_details["agent"]["agentStatus"]
395
+ while (agent_status == "CREATING") and (counter <= 9):
396
+ counter = counter + 1
397
+ time.sleep(1)
398
+ agent_details = self.bedrock_agent_client.get_agent(agentId=self.agent_id)
399
+ agent_status = agent_details["agent"]["agentStatus"]
400
+
401
+ if counter == 10:
402
+ error = f"Error creating agent timeout. Agent created, but status never transitioned out of CREATING"
403
+ self.logger.error(error)
404
+ raise RuntimeError(error)
405
+
406
+ try:
407
+ agent_action_group = self.bedrock_agent_client.create_agent_action_group(
408
+ **args
409
+ )
410
+ self.agent_action_group_id = agent_action_group["agentActionGroup"][
411
+ "actionGroupId"
412
+ ]
413
+ except ClientError as e:
414
+ error = f"Error creating agent action group. Client error: {e}"
415
+ self.logger.error(error)
416
+ raise RuntimeError(error)
417
+ except Exception as e:
418
+ error = f"Error creating agent action group. Unexpected error: {e}"
419
+ self.logger.error(error)
420
+ raise RuntimeError(error)
421
+
422
+ return agent_action_group
423
+
424
+ def _create_agent_role(self) -> str:
425
+ """Create IAM agent role for Bedrock integration"""
426
+
427
+ iam = boto3.client("iam")
428
+
429
+ self.agent_role_name = f"{self.app_id}_bedrock_agent_execution_role"
430
+ self.agent_policy_name = f"{self.app_id}_bedrock_agent_allow_model"
431
+
432
+ assume_role = self._get_assumed_role(service="bedrock.amazonaws.com")
433
+
434
+ try:
435
+ iam.create_role(
436
+ RoleName=self.agent_role_name,
437
+ AssumeRolePolicyDocument=json.dumps(assume_role),
438
+ )
439
+ except ClientError as e:
440
+ error = f"Error creating agent role. Client error: {e}"
441
+ self.logger.error(error)
442
+ raise RuntimeError(error)
443
+ except Exception as e:
444
+ error = f"Error creating agent role. Unexpected error: {e}"
445
+ self.logger.error(error)
446
+ raise RuntimeError(error)
447
+
448
+ managed_policy_txt = self._get_managed_policy(
449
+ resource=f"foundation-model/{self.agent_target_model}"
450
+ )
451
+
452
+ try:
453
+ managed_policy = iam.create_policy(
454
+ PolicyName=self.agent_policy_name,
455
+ PolicyDocument=json.dumps(managed_policy_txt),
456
+ )
457
+ except ClientError as e:
458
+ error = f"Error creating agent policy. Client error: {e}"
459
+ self.logger.error(error)
460
+ raise RuntimeError(error)
461
+ except Exception as e:
462
+ error = f"Error creating agent policy. Unexpected error: {e}"
463
+ self.logger.error(error)
464
+ raise RuntimeError(error)
465
+
466
+ self.agent_role_policy_arn = (
467
+ f"arn:aws:iam::{self.aws_account_id}:policy/{self.agent_policy_name}"
468
+ )
469
+ try:
470
+ iam.attach_role_policy(
471
+ RoleName=self.agent_role_name,
472
+ PolicyArn=self.agent_role_policy_arn,
473
+ )
474
+ except ClientError as e:
475
+ error = f"Error creating attaching policy to agent role. Client error: {e}"
476
+ self.logger.error(error)
477
+ raise RuntimeError(error)
478
+ except Exception as e:
479
+ error = (
480
+ f"Error creating attaching policy to agent role. Unexpected error: {e}"
481
+ )
482
+ self.logger.error(error)
483
+ raise RuntimeError(error)
484
+
485
+ return iam.get_role(RoleName=self.agent_role_name)["Role"]["Arn"]
486
+
487
+ def _get_assumed_role(self, service: str = None) -> str:
488
+ """Skeleton code for creating a role"""
489
+ role = {
490
+ "Version": "2012-10-17",
491
+ "Statement": [
492
+ {
493
+ "Effect": "Allow",
494
+ "Principal": {"Service": f"{service}"},
495
+ "Action": "sts:AssumeRole",
496
+ }
497
+ ],
498
+ }
499
+ return role
500
+
501
+ def _get_managed_policy(self, resource: str = None) -> str:
502
+ """Skeleton code for creating a policy"""
503
+ managed_policy_txt = {
504
+ "Version": "2012-10-17",
505
+ "Statement": [
506
+ {
507
+ "Action": "bedrock:InvokeModel",
508
+ "Resource": f"arn:aws:bedrock:us-east-1::{resource}",
509
+ "Effect": "Allow",
510
+ }
511
+ ],
512
+ }
513
+
514
+ return managed_policy_txt
515
+
516
+ def _get_lambda_source(
517
+ self, module_name: str = None, class_name: str = None
518
+ ) -> str:
519
+ """Bedrock wrapped lambda used by the agent"""
520
+
521
+ # funky spacing below is required...
522
+ lambda_src = f"""
523
+ import json
524
+ from {module_name} import {class_name}
525
+
526
+
527
+ def lambda_handler(event, context):
528
+ tool = {class_name}()
529
+ result = tool.fn()
530
+ action_response = {{
531
+ "actionGroup": event["actionGroup"],
532
+ "apiPath": event["apiPath"],
533
+ "httpMethod": event["httpMethod"],
534
+ "httpStatusCode": 200,
535
+ "responseBody": {{"application/json": {{"body": json.dumps(result)}}}},
536
+ }}
537
+ api_response = {{"messageVersion": "1.0", "response": action_response}}
538
+
539
+ return api_response"""
540
+ return lambda_src
541
+
542
+ def delete_app(self, bedrock_config: dict = None) -> bool:
543
+ """Tear down the boto3 stack created by .export_to_bedrock()"""
544
+
545
+ valid_bedrock_config_schema = {
546
+ "type": "object",
547
+ "properties": {
548
+ "lambdaARN": {"type": "string"},
549
+ "lambdaRoleName": {"type": "string"},
550
+ "agentId": {"type": "string"},
551
+ "agentRoleName": {"type": "string"},
552
+ "agentPolicyARN": {"type": "string"},
553
+ "agentActionGroup": {"type": "string"},
554
+ },
555
+ "required": [
556
+ "lambdaARN",
557
+ "lambdaRoleName",
558
+ "agentId",
559
+ "agentRoleName",
560
+ "agentPolicyARN",
561
+ "agentActionGroup",
562
+ ],
563
+ }
564
+ try:
565
+ validate(bedrock_config, valid_bedrock_config_schema)
566
+ except jsonschema.exceptions.ValidationError as err:
567
+ error = f"JSON validation failure on input bedrock_config: {err}"
568
+ self.logger.error(error)
569
+ raise RuntimeError(error)
570
+
571
+ self.lambda_client = boto3.client("lambda")
572
+ self.iam_client = boto3.client("iam")
573
+ self.bedrock_agent_client = boto3.client("bedrock-agent")
574
+
575
+ # Order is important here...
576
+ try:
577
+ detach_agent_policy = self.iam_client.detach_role_policy(
578
+ RoleName=bedrock_config["agentRoleName"],
579
+ PolicyArn=bedrock_config["agentPolicyARN"],
580
+ )
581
+ except ClientError as e:
582
+ error = f"Error detaching agent policy. Client error: {e}"
583
+ self.logger.error(error)
584
+ pass
585
+ except Exception as e:
586
+ error = f"Error detaching agent policy. Unexpected error: {e}"
587
+ self.logger.error(error)
588
+ pass
589
+ try:
590
+ delete_agent_role = self.iam_client.delete_role(
591
+ RoleName=bedrock_config["agentRoleName"]
592
+ )
593
+ except ClientError as e:
594
+ error = f"Error deleting agent role. Client error: {e}"
595
+ self.logger.error(error)
596
+ pass
597
+ except Exception as e:
598
+ error = f"Error deleting agent role. Unexpected error: {e}"
599
+ self.logger.error(error)
600
+ pass
601
+
602
+ try:
603
+ delete_agent_policy = self.iam_client.delete_policy(
604
+ PolicyArn=bedrock_config["agentPolicyARN"]
605
+ )
606
+ except ClientError as e:
607
+ error = f"Error deleting agent policy. Client error: {e}"
608
+ self.logger.error(error)
609
+ pass
610
+ except Exception as e:
611
+ error = f"Error deleting agent policy. Unexpected error: {e}"
612
+ self.logger.error(error)
613
+ pass
614
+
615
+ try:
616
+ delete_agent = self.bedrock_agent_client.delete_agent(
617
+ agentId=bedrock_config["agentId"], skipResourceInUseCheck=True
618
+ )
619
+ except ClientError as e:
620
+ error = f"Error deleting agent. Client error: {e}"
621
+ self.logger.error(error)
622
+ pass
623
+ except Exception as e:
624
+ error = f"Error deleting agent. Unexpected error: {e}"
625
+ self.logger.error(error)
626
+ pass
627
+
628
+ try:
629
+ detach_lambda_policy = self.iam_client.detach_role_policy(
630
+ RoleName=bedrock_config["lambdaRoleName"],
631
+ PolicyArn="arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole",
632
+ )
633
+ except ClientError as e:
634
+ error = f"Error detaching lambda policy. Client error: {e}"
635
+ self.logger.error(error)
636
+ pass
637
+ except Exception as e:
638
+ error = f"Error detaching lambda policy. Unexpected error: {e}"
639
+ self.logger.error(error)
640
+ pass
641
+
642
+ try:
643
+ delete_lambda_role = self.iam_client.delete_role(
644
+ RoleName=bedrock_config["lambdaRoleName"]
645
+ )
646
+ except ClientError as e:
647
+ error = f"Error deleting lambda role. Client error: {e}"
648
+ self.logger.error(error)
649
+ pass
650
+ except Exception as e:
651
+ error = f"Error deleting lambda role. Unexpected error: {e}"
652
+ self.logger.error(error)
653
+ pass
654
+
655
+ try:
656
+ delete_lambda = self.lambda_client.delete_function(
657
+ FunctionName=bedrock_config["lambdaARN"]
658
+ )
659
+ except ClientError as e:
660
+ error = f"Error deleting lambda. Client error: {e}"
661
+ self.logger.error(error)
662
+ pass
663
+ except Exception as e:
664
+ error = f"Error deleting lambda. Unexpected error: {e}"
665
+ self.logger.error(error)
666
+ pass