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.

165 lines
5.9 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. # a bucket in S3 will be created to store the counter bucket names need to be world-wide unique ;)
  11. # Hence we create a bucket name that contains your group number and the current year.
  12. # The counter will be stores as key (file) "us-east-1" in the bucket (same name as our default region)
  13. # in the bucket and expects a number in it to increase
  14. groupNr = 22
  15. currentYear = date.today().year
  16. globallyUniqueS3GroupBucketName = "cloudcomp-counter-" + str(currentYear) + "-group" + str(groupNr)
  17. # region = 'eu-central-1'
  18. region = 'us-east-1'
  19. functionName = 'cloudcomp-counter-lambda-demo'
  20. # The Lambda function will run using privileges of a role, that allows the function to access/create
  21. # resources in AWS (in this case read/write to S3). In AWS Academy you need to use the role that
  22. # use created for your student account in the lab (see lab readme).
  23. # see ARN for AWS Academy LabRole function here:
  24. # https://us-east-1.console.aws.amazon.com/iamv2/home?region=us-east-1#/roles/details/LabRole?section=permissions
  25. #
  26. # e.g.: (309000625112, 919927306708, 488766701848 would in your case be your AWS Account ID, see Lab Details)
  27. #
  28. # roleArn = 'arn:aws:iam::309000625112:role/service-role/cloudcomp-counter-demo-role-6rs7pah3'
  29. # roleArn = 'arn:aws:iam::919927306708:role/cloudcomp-s3-access'
  30. # roleArn = 'arn:aws:iam::488766701848:role/LabRole'
  31. # standard name for role in AWS Academy lab created by vocareum is "LabRole". See README of the
  32. # lab. The following code will lookup the AWS Resource Name (ARN) (sort of the ID for this role)
  33. # that has the following name:
  34. roleName = "LabRole"
  35. ################################################################################################
  36. #
  37. # boto3 code
  38. #
  39. ################################################################################################
  40. def cleanup_s3_bucket(s3_bucket):
  41. # Deleting objects
  42. for s3_object in s3_bucket.objects.all():
  43. s3_object.delete()
  44. # Deleting objects versions if S3 versioning enabled
  45. for s3_object_ver in s3_bucket.object_versions.all():
  46. s3_object_ver.delete()
  47. client = boto3.setup_default_session(region_name=region)
  48. iamClient = boto3.client('iam')
  49. s3Client = boto3.client('s3')
  50. s3Resource = boto3.resource('s3')
  51. lClient = boto3.client('lambda')
  52. apiClient = boto3.client("apigatewayv2")
  53. print("Getting AWS Academy LabRole ARN...")
  54. print("------------------------------------")
  55. response = iamClient.list_roles()
  56. for role in response["Roles"]:
  57. if role["RoleName"] == roleName:
  58. roleArn = role["Arn"]
  59. print(roleArn)
  60. print("Searching for old API gateway...")
  61. print("------------------------------------")
  62. for api in apiClient.get_apis()["Items"]:
  63. if api["Name"] == functionName + '-api':
  64. print("Deleting old API gateway...")
  65. print("------------------------------------")
  66. response = apiClient.delete_api(
  67. ApiId=api["ApiId"],
  68. )
  69. print("Deleting old function...")
  70. print("------------------------------------")
  71. try:
  72. response = lClient.delete_function(
  73. FunctionName=functionName,
  74. )
  75. except lClient.exceptions.ResourceNotFoundException:
  76. print('Function not available. No need to delete it.')
  77. print("Deleting old bucket...")
  78. print("------------------------------------")
  79. try:
  80. currentBucket = s3Resource.Bucket(globallyUniqueS3GroupBucketName)
  81. cleanup_s3_bucket(currentBucket)
  82. currentBucket.delete()
  83. except s3Client.exceptions.NoSuchBucket:
  84. print('Bucket not available. No need to delete it.')
  85. print("creating S3 bucket (must be globally unique)...")
  86. print("------------------------------------")
  87. try:
  88. response = s3Client.create_bucket(Bucket=globallyUniqueS3GroupBucketName)
  89. response = s3Client.put_object(Bucket=globallyUniqueS3GroupBucketName, Key='us-east-1', Body=str(0))
  90. except ClientError as e:
  91. print(e)
  92. print("creating new function...")
  93. print("------------------------------------")
  94. zf = zipfile.ZipFile('lambda-deployment-archive.zip', 'w', zipfile.ZIP_DEFLATED)
  95. zf.write('lambda_function.py')
  96. zf.close()
  97. lambdaFunctionARN = ""
  98. with open('lambda-deployment-archive.zip', mode='rb') as file:
  99. zipfileContent = file.read()
  100. response = lClient.create_function(
  101. FunctionName=functionName,
  102. Runtime='python3.9',
  103. Role=roleArn,
  104. Code={
  105. 'ZipFile': zipfileContent
  106. },
  107. Handler='lambda_function.lambda_handler',
  108. Publish=True,
  109. Environment={
  110. 'Variables': {
  111. 'bucketName': globallyUniqueS3GroupBucketName
  112. }
  113. }
  114. )
  115. lambdaFunctionARN = response['FunctionArn']
  116. # API gateway to get an HTTP endpoint that we can access directly in the browser,
  117. # which will call our function, as in the provided demo:
  118. # https://348yxdily0.execute-api.eu-central-1.amazonaws.com/default/cloudcomp-counter-demo
  119. print("creating API gateway...")
  120. print("------------------------------------")
  121. response = apiClient.create_api(
  122. Name=functionName + '-api',
  123. ProtocolType='HTTP',
  124. Target=lambdaFunctionARN,
  125. CredentialsArn=roleArn
  126. )
  127. print("Lambda Function and S3 Bucket to store the counter are created.\n"
  128. "\n"
  129. "You can access the API gateway and increment the counter using the created Lambda function\n"
  130. "at: " + response["ApiEndpoint"] + " \n"
  131. "You can also run invoke-function.py to view an increment the counter. You can also use \n"
  132. "the test button in the Lambda AWS console. In this case you need to send the content\n"
  133. "\n"
  134. "{\n"
  135. " \"input\": \"1\"\n"
  136. "}\n"
  137. "\n"
  138. "to increment the counter by 1.\n"
  139. "Try to understand how Lambda can be used to cut costs regarding cloud services and what its pros\n"
  140. "and cons are.\n")