/aws-py-serverless-raw/__main__.py

https://github.com/pulumi/examples · Python · 150 lines · 103 code · 21 blank · 26 comment · 1 complexity · 3d675315f331c43aeee854f7d6038038 MD5 · raw file

  1. """Copyright 2016-2019, Pulumi Corporation. All rights reserved."""
  2. import json
  3. import pulumi
  4. import pulumi_aws as aws
  5. # The location of the built dotnet3.1 application to deploy
  6. dotnet_application_publish_folder = "./app/bin/Debug/netcoreapp3.1/publish"
  7. dotnet_application_entry_point = "app::app.Functions::GetAsync"
  8. # The stage name to use for the API Gateway URL
  9. custom_stage_name = "api"
  10. region = aws.config.region
  11. #################
  12. ## DynamoDB Table
  13. #################
  14. # A DynamoDB table with a single primary key
  15. counter_table = aws.dynamodb.Table("counterTable",
  16. attributes=[
  17. aws.dynamodb.TableAttributeArgs(
  18. name="Id",
  19. type="S",
  20. ),
  21. ],
  22. hash_key="Id",
  23. read_capacity=1,
  24. write_capacity=1,
  25. )
  26. ##################
  27. ## Lambda Function
  28. ##################
  29. # Give our Lambda access to the Dynamo DB table, CloudWatch Logs and Metrics
  30. # Python package does not have assumeRolePolicyForPrinciple
  31. instance_assume_role_policy = aws.iam.get_policy_document(
  32. statements=[aws.iam.GetPolicyDocumentStatementArgs(
  33. actions=["sts:AssumeRole"],
  34. principals=[aws.iam.GetPolicyDocumentStatementPrincipalArgs(
  35. identifiers=["lambda.amazonaws.com"],
  36. type="Service",
  37. )],
  38. )])
  39. role = aws.iam.Role("mylambda-role",
  40. assume_role_policy=instance_assume_role_policy.json,
  41. )
  42. policy = aws.iam.RolePolicy("mylambda-policy",
  43. role=role.id,
  44. policy=counter_table.arn.apply(lambda arn: json.dumps({
  45. "Version": "2012-10-17",
  46. "Statement": [{
  47. "Action": ["dynamodb:UpdateItem", "dynamodb:PutItem", "dynamodb:GetItem",
  48. "dynamodb:DescribeTable"],
  49. "Resource": arn,
  50. "Effect": "Allow",
  51. }, {
  52. "Action": ["logs:*", "cloudwatch:*"],
  53. "Resource": "*",
  54. "Effect": "Allow",
  55. }],
  56. })))
  57. # Read the config of whether to provision fixed concurrency for Lambda
  58. config = pulumi.Config()
  59. provisioned_concurrent_executions = config.get_float('provisionedConcurrency')
  60. # Create a Lambda function, using code from the `./app` folder.
  61. lambda_func = aws.lambda_.Function("mylambda",
  62. opts=pulumi.ResourceOptions(depends_on=[policy]),
  63. runtime="dotnetcore3.1",
  64. code=pulumi.AssetArchive({
  65. ".": pulumi.FileArchive(dotnet_application_publish_folder),
  66. }),
  67. timeout=300,
  68. handler=dotnet_application_entry_point,
  69. role=role.arn,
  70. publish=bool(provisioned_concurrent_executions),
  71. # Versioning required for provisioned concurrency
  72. environment=aws.lambda_.FunctionEnvironmentArgs(
  73. variables={
  74. "COUNTER_TABLE": counter_table.name,
  75. },
  76. ),
  77. )
  78. if provisioned_concurrent_executions:
  79. concurrency = aws.lambda_.ProvisionedConcurrencyConfig("concurrency",
  80. function_name=lambda_func.name,
  81. qualifier=lambda_func.version,
  82. provisioned_concurrent_executions=provisioned_concurrent_executions
  83. )
  84. #####################
  85. ## APIGateway RestAPI
  86. ######################
  87. # Create a single Swagger spec route handler for a Lambda function.
  88. def swagger_route_handler(arn):
  89. return ({
  90. "x-amazon-apigateway-any-method": {
  91. "x-amazon-apigateway-integration": {
  92. "uri": f'arn:aws:apigateway:{region}:lambda:path/2015-03-31/functions/{arn}/invocations',
  93. "passthroughBehavior": "when_no_match",
  94. "httpMethod": "POST",
  95. "type": "aws_proxy",
  96. },
  97. },
  98. })
  99. # Create the API Gateway Rest API, using a swagger spec.
  100. rest_api = aws.apigateway.RestApi("api",
  101. body=lambda_func.arn.apply(lambda arn: json.dumps({
  102. "swagger": "2.0",
  103. "info": {"title": "api", "version": "1.0"},
  104. "paths": {
  105. "/{proxy+}": swagger_route_handler(arn),
  106. },
  107. })))
  108. # Create a deployment of the Rest API.
  109. deployment = aws.apigateway.Deployment("api-deployment",
  110. rest_api=rest_api.id,
  111. # Note: Set to empty to avoid creating an implicit stage, we'll create it
  112. # explicitly below instead.
  113. stage_name="",
  114. )
  115. # Create a stage, which is an addressable instance of the Rest API. Set it to point at the latest deployment.
  116. stage = aws.apigateway.Stage("api-stage",
  117. rest_api=rest_api.id,
  118. deployment=deployment.id,
  119. stage_name=custom_stage_name,
  120. )
  121. # Give permissions from API Gateway to invoke the Lambda
  122. invoke_permission = aws.lambda_.Permission("api-lambda-permission",
  123. action="lambda:invokeFunction",
  124. function=lambda_func.name,
  125. principal="apigateway.amazonaws.com",
  126. source_arn=deployment.execution_arn.apply(lambda arn: arn + "*/*"),
  127. )
  128. # Export the https endpoint of the running Rest API
  129. pulumi.export("endpoint", deployment.invoke_url.apply(lambda url: url + custom_stage_name))