33import argparse
44import contextlib
55import json
6+ import logging
67import os
78import shutil
89import sys
910import zipfile
1011from pathlib import Path
1112
1213
14+ # Configure logging
15+ logging .basicConfig (level = logging .INFO , format = "%(levelname)s: %(message)s" )
16+ logger = logging .getLogger (__name__ )
17+
18+
1319try :
1420 import boto3
1521 from aws_durable_execution_sdk_python .lambda_service import LambdaClient
@@ -30,8 +36,11 @@ def build_examples():
3036 build_dir = Path (__file__ ).parent / "build"
3137 src_dir = Path (__file__ ).parent / "src"
3238
39+ logger .info ("Building examples..." )
40+
3341 # Clean and create build directory
3442 if build_dir .exists ():
43+ logger .info ("Cleaning existing build directory" )
3544 shutil .rmtree (build_dir )
3645 build_dir .mkdir ()
3746
@@ -40,8 +49,10 @@ def build_examples():
4049 import aws_durable_execution_sdk_python
4150
4251 sdk_path = Path (aws_durable_execution_sdk_python .__file__ ).parent
52+ logger .info ("Copying SDK from %s" , sdk_path )
4353 shutil .copytree (sdk_path , build_dir / "aws_durable_execution_sdk_python" )
4454 except (ImportError , OSError ):
55+ logger .exception ("Failed to copy SDK" )
4556 return False
4657
4758 # Copy testing SDK source
@@ -50,11 +61,14 @@ def build_examples():
5061 / "src"
5162 / "aws_durable_execution_sdk_python_testing"
5263 )
64+ logger .info ("Copying testing SDK from %s" , testing_src )
5365 shutil .copytree (testing_src , build_dir / "aws_durable_execution_sdk_python_testing" )
5466
5567 # Copy example functions
68+ logger .info ("Copying examples from %s" , src_dir )
5669 shutil .copytree (src_dir , build_dir / "src" )
5770
71+ logger .info ("Build completed successfully" )
5872 return True
5973
6074
@@ -259,10 +273,17 @@ def create_deployment_package(example_name: str) -> Path:
259273
260274 zip_path = Path (__file__ ).parent / f"{ example_name } .zip"
261275 with zipfile .ZipFile (zip_path , "w" , zipfile .ZIP_DEFLATED ) as zf :
276+ # Add SDK dependencies
262277 for file_path in build_dir .rglob ("*" ):
263- if file_path .is_file ():
278+ if file_path .is_file () and not file_path . is_relative_to ( build_dir / "src" ) :
264279 zf .write (file_path , file_path .relative_to (build_dir ))
265280
281+ # Add example files at root level
282+ src_dir = build_dir / "src"
283+ for file_path in src_dir .rglob ("*" ):
284+ if file_path .is_file ():
285+ zf .write (file_path , file_path .relative_to (src_dir ))
286+
266287 return zip_path
267288
268289
@@ -308,6 +329,7 @@ def deploy_function(example_name: str, function_name: str | None = None):
308329 break
309330
310331 if not example_config :
332+ logger .error ("Example not found: '%s'" , example_name )
311333 list_examples ()
312334 return False
313335
@@ -331,7 +353,7 @@ def deploy_function(example_name: str, function_name: str | None = None):
331353 "Description" : example_config ["description" ],
332354 "Timeout" : 60 ,
333355 "MemorySize" : 128 ,
334- "Environment" : {"Variables" : {"DEX_ENDPOINT " : config ["lambda_endpoint" ]}},
356+ # "Environment": {"Variables": {"AWS_ENDPOINT_URL_LAMBDA ": config["lambda_endpoint"]}},
335357 "DurableConfig" : example_config ["durableConfig" ],
336358 }
337359
@@ -351,15 +373,47 @@ def deploy_function(example_name: str, function_name: str | None = None):
351373 except lambda_client .exceptions .ResourceNotFoundException :
352374 lambda_client .create_function (** function_config , Code = {"ZipFile" : zip_content })
353375
354- # Add invoke permission
355- with contextlib .suppress (lambda_client .exceptions .ResourceConflictException ):
376+ # Update invoke permission for worker account if needed
377+ try :
378+ policy_response = lambda_client .get_policy (FunctionName = function_name )
379+ policy = json .loads (policy_response ["Policy" ])
380+
381+ # Check if permission exists with correct principal
382+ needs_update = True
383+ for statement in policy .get ("Statement" , []):
384+ if (
385+ statement .get ("Sid" ) == "dex-invoke-permission"
386+ and statement .get ("Principal" , {}).get ("AWS" )
387+ == config ["invoke_account_id" ]
388+ ):
389+ needs_update = False
390+ break
391+
392+ if needs_update :
393+ with contextlib .suppress (
394+ lambda_client .exceptions .ResourceNotFoundException
395+ ):
396+ lambda_client .remove_permission (
397+ FunctionName = function_name , StatementId = "dex-invoke-permission"
398+ )
399+
400+ lambda_client .add_permission (
401+ FunctionName = function_name ,
402+ StatementId = "dex-invoke-permission" ,
403+ Action = "lambda:InvokeFunction" ,
404+ Principal = config ["invoke_account_id" ],
405+ )
406+
407+ except lambda_client .exceptions .ResourceNotFoundException :
408+ # No policy exists, add permission
356409 lambda_client .add_permission (
357410 FunctionName = function_name ,
358411 StatementId = "dex-invoke-permission" ,
359412 Action = "lambda:InvokeFunction" ,
360413 Principal = config ["invoke_account_id" ],
361414 )
362415
416+ logger .info ("Function deployed successfully! %s" , function_name )
363417 return True
364418
365419
@@ -419,8 +473,9 @@ def get_function_policy(function_name: str):
419473def list_examples ():
420474 """List available examples."""
421475 catalog = load_catalog ()
422- for _example in catalog ["examples" ]:
423- pass
476+ logger .info ("Available examples:" )
477+ for example in catalog ["examples" ]:
478+ logger .info (" - %s: %s" , example ["name" ], example ["description" ])
424479
425480
426481def main ():
0 commit comments