You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

150 lines
5.4 KiB

  1. from datetime import date
  2. import zipfile
  3. import boto3
  4. from botocore.exceptions import ClientError
  5. ################################################################################################
  6. #
  7. # Configuration Parameters
  8. #
  9. ################################################################################################
  10. # main change from real AWS Academy access to local emulated localstack is to change the endpoint
  11. # other than that the same tools (boto3, aws-cli, aws-cdk etc. can be used)
  12. endpoint_url = "http://localhost.localstack.cloud:4566"
  13. # a bucket in S3 will be created to store the counter bucket names need to be world-wide unique ;)
  14. # Hence we create a bucket name that contains your group number and the current year.
  15. # The counter will be stores as key (file) "us-east-1" in the bucket (same name as our default region)
  16. # in the bucket and expects a number in it to increase
  17. groupNr = 22
  18. currentYear = date.today().year
  19. globallyUniqueS3GroupBucketName = "cloudcomp-counter-" + str(currentYear) + "-group" + str(groupNr)
  20. # region = 'eu-central-1'
  21. region = 'us-east-1'
  22. functionName = 'cloudcomp-counter-lambda-demo'
  23. # The Lambda function will run using privileges of a role, that allows the function to access/create
  24. # resources in AWS (in this case read/write to S3). In AWS Academy you need to use the role that
  25. # use created for your student account in the lab (see lab readme).
  26. # see ARN for AWS Academy LabRole function here:
  27. # https://us-east-1.console.aws.amazon.com/iamv2/home?region=us-east-1#/roles/details/LabRole?section=permissions
  28. #
  29. # roleArn = 'arn:aws:iam::309000625112:role/service-role/cloudcomp-counter-demo-role-6rs7pah3'
  30. # roleArn = 'arn:aws:iam::919927306708:role/cloudcomp-s3-access'
  31. roleArn = 'arn:aws:iam::488766701848:role/LabRole'
  32. # For localstack you can use any role Arn and every secret and access key. Hence you can also use
  33. # existing AWS Academy credentials to connect to localstack
  34. ################################################################################################
  35. #
  36. # boto3 code
  37. #
  38. ################################################################################################
  39. def cleanup_s3_bucket(s3_bucket):
  40. # Deleting objects
  41. for s3_object in s3_bucket.objects.all():
  42. s3_object.delete()
  43. # Deleting objects versions if S3 versioning enabled
  44. for s3_object_ver in s3_bucket.object_versions.all():
  45. s3_object_ver.delete()
  46. client = boto3.setup_default_session(region_name=region)
  47. s3Client = boto3.client('s3', endpoint_url=endpoint_url)
  48. s3Resource = boto3.resource('s3', endpoint_url=endpoint_url)
  49. lClient = boto3.client('lambda', endpoint_url=endpoint_url)
  50. apiClient = boto3.client("apigatewayv2", endpoint_url=endpoint_url)
  51. print("Deleting old API gateway...")
  52. print("------------------------------------")
  53. response = apiClient.get_apis()
  54. for api in response["Items"]:
  55. if api["Name"] == functionName + '-api':
  56. responseDelete = apiClient.delete_api(
  57. ApiId=api["ApiId"]
  58. )
  59. print("Deleting old function...")
  60. print("------------------------------------")
  61. try:
  62. response = lClient.delete_function(
  63. FunctionName=functionName,
  64. )
  65. except lClient.exceptions.ResourceNotFoundException:
  66. print('Function not available. No need to delete it.')
  67. print("Deleting old bucket...")
  68. print("------------------------------------")
  69. try:
  70. currentBucket = s3Resource.Bucket(globallyUniqueS3GroupBucketName)
  71. cleanup_s3_bucket(currentBucket)
  72. currentBucket.delete()
  73. except ClientError as e:
  74. print(e)
  75. print("creating S3 bucket (must be globally unique)...")
  76. print("------------------------------------")
  77. try:
  78. response = s3Client.create_bucket(Bucket=globallyUniqueS3GroupBucketName)
  79. response = s3Client.put_object(Bucket=globallyUniqueS3GroupBucketName, Key='us-east-1', Body=str(0))
  80. except ClientError as e:
  81. print(e)
  82. print("creating new function...")
  83. print("------------------------------------")
  84. zf = zipfile.ZipFile('lambda-deployment-archive.zip', 'w', zipfile.ZIP_DEFLATED)
  85. zf.write('lambda_function.py')
  86. zf.close()
  87. lambdaFunctionARN = ""
  88. with open('lambda-deployment-archive.zip', mode='rb') as file:
  89. zipfileContent = file.read()
  90. response = lClient.create_function(
  91. FunctionName=functionName,
  92. Runtime='python3.9',
  93. Role=roleArn,
  94. Code={
  95. 'ZipFile': zipfileContent
  96. },
  97. Handler='lambda_function.lambda_handler',
  98. Publish=True,
  99. Environment={
  100. 'Variables': {
  101. 'bucketName': globallyUniqueS3GroupBucketName
  102. }
  103. }
  104. )
  105. lambdaFunctionARN = response['FunctionArn']
  106. print("Lambda Function and S3 Bucket to store the counter are available.\n"
  107. "\n"
  108. "You can now run invoke-function.py to view an increment the counter.\n"
  109. "Try to understand how Lambda can be used to cut costs regarding cloud services and what its pros\n"
  110. "and cons are.\n")
  111. # sadly, AWS Academy Labs don't allow API gateways
  112. # API gateway would allow getting an HTTP endpoint that we could access directly in the browser,
  113. # that would call our function, as in the provided demo:
  114. #
  115. # https://348yxdily0.execute-api.eu-central-1.amazonaws.com/default/cloudcomp-counter-demo
  116. print("creating API gateway...")
  117. print("------------------------------------")
  118. response = apiClient.create_api(
  119. Name=functionName + '-api',
  120. ProtocolType='HTTP',
  121. Target=lambdaFunctionARN
  122. )
  123. apiArn = response
  124. print("API Endpoint can be reached at: http://" + apiArn["ApiEndpoint"])