forked from pulumi/examples
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request pulumi#732 from pulumi/zephyrz73/serverless-raw-co…
…nversion 1. Change the netcore version to 3.1 2. Converted the project aws-ts-serverless-raw into aws-py-serverless-raw
- Loading branch information
Showing
12 changed files
with
395 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
*.pyc | ||
venv/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
name: serverless-raw | ||
runtime: python | ||
description: Basic example of a serverless AWS application | ||
template: | ||
config: | ||
aws:region: | ||
description: The AWS region to deploy into | ||
default: us-east-2 | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
[![Deploy](https://get.pulumi.com/new/button.svg)](https://app.pulumi.com/new) | ||
|
||
# Serverless C# App | ||
|
||
This example deploys a complete serverless C# application using raw `aws.apigateway.RestApi`, `aws.lambda_.Function` and | ||
`aws.dynamodb.Table` resources from `pulumi_aws`. Although this doesn't feature any of the higher-level abstractions | ||
from the `pulumi_cloud` package, it demonstrates that you can program the raw resources directly available in AWS | ||
to accomplish all of the same things this higher-level package offers. | ||
|
||
The deployed Lambda function is a simple C# application, highlighting the ability to manage existing application code | ||
in a Pulumi application, even if your Pulumi code is written in a different language like JavaScript or Python. | ||
|
||
The Lambda function is a C# application using .NET Core 3.1 (a similar approach works for any other language supported by | ||
AWS Lambda). | ||
|
||
## Deploying and running the Pulumi App | ||
1. Install dependencies. In this example we will install them in a virtual environment named `venv`. | ||
```bash | ||
$ python3 -m venv venv | ||
$ source venv/bin/activate | ||
$ pip install -r requirements.txt | ||
``` | ||
|
||
1. Create a new stack: | ||
|
||
```bash | ||
$ pulumi stack init dev | ||
``` | ||
|
||
1. Build the C# application. | ||
|
||
```bash | ||
dotnet publish app | ||
``` | ||
|
||
1. Set the AWS region: | ||
|
||
```bash | ||
$ pulumi config set aws:region us-east-2 | ||
``` | ||
|
||
1. Optionally, set AWS Lambda provisioned concurrency: | ||
|
||
```bash | ||
$ pulumi config set provisionedConcurrency 1 | ||
``` | ||
|
||
1. Run `pulumi up` to preview and deploy changes: | ||
|
||
``` | ||
$ pulumi up | ||
Previewing update (dev): | ||
... | ||
|
||
Updating (dev): | ||
... | ||
Resources: | ||
+ 10 created | ||
Duration: 1m 20s | ||
``` | ||
|
||
1. Check the deployed GraphQL endpoint: | ||
|
||
``` | ||
$ curl $(pulumi stack output endpoint)/hello | ||
{"Path":"/hello","Count":0} | ||
``` | ||
|
||
1. See the logs | ||
|
||
``` | ||
$ pulumi logs -f | ||
2018-03-21T18:24:52.670-07:00[ mylambda-d719650] START RequestId: d1e95652-2d6f-11e8-93f6-2921c8ae65e7 Version: $LATEST | ||
2018-03-21T18:24:56.171-07:00[ mylambda-d719650] Getting count for '/hello' | ||
2018-03-21T18:25:01.327-07:00[ mylambda-d719650] Got count 0 for '/hello' | ||
2018-03-21T18:25:02.267-07:00[ mylambda-d719650] END RequestId: d1e95652-2d6f-11e8-93f6-2921c8ae65e7 | ||
2018-03-21T18:25:02.267-07:00[ mylambda-d719650] REPORT RequestId: d1e95652-2d6f-11e8-93f6-2921c8ae65e7 Duration: 9540.93 ms Billed Duration: 9600 ms Memory Size: 128 MB Max Memory Used: 37 MB | ||
``` | ||
|
||
## Clean up | ||
|
||
1. Run `pulumi destroy` to tear down all resources. | ||
|
||
1. To delete the stack itself, run `pulumi stack rm`. Note that this command deletes all deployment history from the Pulumi Console. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,160 @@ | ||
"""Copyright 2016-2019, Pulumi Corporation. All rights reserved.""" | ||
import pulumi | ||
import pulumi_aws as aws | ||
import pulumi_aws.config | ||
from pulumi import Output | ||
import json | ||
|
||
# The location of the built dotnet3.1 application to deploy | ||
dotnet_application_publish_folder = "./app/bin/Debug/netcoreapp3.1/publish" | ||
dotnet_application_entry_point = "app::app.Functions::GetAsync" | ||
# The stage name to use for the API Gateway URL | ||
custom_stage_name = "api" | ||
|
||
################# | ||
## DynamoDB Table | ||
################# | ||
|
||
# A DynamoDB table with a single primary key | ||
counter_table = aws.dynamodb.Table("counterTable", | ||
attributes=[ | ||
{ | ||
"name": "Id", | ||
"type": "S", | ||
}, | ||
], | ||
hash_key="Id", | ||
read_capacity=1, | ||
write_capacity=1, | ||
) | ||
|
||
################## | ||
## Lambda Function | ||
################## | ||
|
||
# Give our Lambda access to the Dynamo DB table, CloudWatch Logs and Metrics | ||
# Python package does not have assumeRolePolicyForPrinciple | ||
instance_assume_role_policy = aws.iam.get_policy_document(statements=[{ | ||
"actions": ["sts:AssumeRole"], | ||
"principals": [{ | ||
"identifiers": ["lambda.amazonaws.com"], | ||
"type": "Service", | ||
}], | ||
}]) | ||
|
||
role = aws.iam.Role("mylambda-role", | ||
assume_role_policy=instance_assume_role_policy.json, | ||
) | ||
|
||
policy = aws.iam.RolePolicy("mylambda-policy", | ||
role=role, | ||
policy=Output.from_input({ | ||
"Version": "2012-10-17", | ||
"Statement": [{ | ||
"Action": ["dynamodb:UpdateItem", "dynamodb:PutItem", "dynamodb:GetItem", | ||
"dynamodb:DescribeTable"], | ||
"Resource": counter_table.arn, | ||
"Effect": "Allow", | ||
}, { | ||
"Action": ["logs:*", "cloudwatch:*"], | ||
"Resource": "*", | ||
"Effect": "Allow", | ||
}], | ||
}), | ||
) | ||
|
||
# Read the config of whether to provision fixed concurrency for Lambda | ||
config = pulumi.Config() | ||
provisioned_concurrent_executions = config.get_float('provisionedConcurrency') | ||
|
||
# Create a Lambda function, using code from the `./app` folder. | ||
|
||
lambda_func = aws.lambda_.Function("mylambda", | ||
opts=pulumi.ResourceOptions(depends_on=[policy]), | ||
runtime="dotnetcore3.1", | ||
code=pulumi.AssetArchive({ | ||
".": pulumi.FileArchive(dotnet_application_publish_folder), | ||
}), | ||
timeout=300, | ||
handler=dotnet_application_entry_point, | ||
role=role.arn, | ||
publish=bool(provisioned_concurrent_executions), | ||
# Versioning required for provisioned concurrency | ||
environment={ | ||
"variables": { | ||
"COUNTER_TABLE": counter_table.name, | ||
}, | ||
}, | ||
) | ||
|
||
if provisioned_concurrent_executions: | ||
concurrency = aws.lambda_.ProvisionedConcurrencyConfig("concurrency", | ||
function_name=lambda_func.name, | ||
qualifier=lambda_func.version, | ||
provisioned_concurrent_executions=provisioned_concurrent_executions, | ||
) | ||
|
||
|
||
##################### | ||
## APIGateway RestAPI | ||
###################### | ||
|
||
# Create the Swagger spec for a proxy which forwards all HTTP requests through to the Lambda function. | ||
def swagger_spec(lambda_arn): | ||
swagger_spec_returns = { | ||
"swagger": "2.0", | ||
"info": {"title": "api", "version": "1.0"}, | ||
"paths": { | ||
"/{proxy+}": swagger_route_handler(lambda_arn), | ||
}, | ||
} | ||
return json.dumps(swagger_spec_returns) | ||
|
||
|
||
# Create a single Swagger spec route handler for a Lambda function. | ||
def swagger_route_handler(lambda_arn): | ||
region = pulumi_aws.config.region | ||
uri_string = 'arn:aws:apigateway:{region}:lambda:path/2015-03-31/functions/{lambdaArn}/invocations'.format( | ||
region=region, lambdaArn=lambda_arn) | ||
return ({ | ||
"x-amazon-apigateway-any-method": { | ||
"x-amazon-apigateway-integration": { | ||
"uri": uri_string, | ||
"passthroughBehavior": "when_no_match", | ||
"httpMethod": "POST", | ||
"type": "aws_proxy", | ||
}, | ||
}, | ||
}) | ||
|
||
|
||
# Create the API Gateway Rest API, using a swagger spec. | ||
rest_api = aws.apigateway.RestApi("api", | ||
body=lambda_func.arn.apply(lambda lambda_arn: swagger_spec(lambda_arn)), | ||
) | ||
|
||
# Create a deployment of the Rest API. | ||
deployment = aws.apigateway.Deployment("api-deployment", | ||
rest_api=rest_api, | ||
# Note: Set to empty to avoid creating an implicit stage, we'll create it | ||
# explicitly below instead. | ||
stage_name="") | ||
|
||
# Create a stage, which is an addressable instance of the Rest API. Set it to point at the latest deployment. | ||
stage = aws.apigateway.Stage("api-stage", | ||
rest_api=rest_api, | ||
deployment=deployment, | ||
stage_name=custom_stage_name, | ||
) | ||
|
||
# Give permissions from API Gateway to invoke the Lambda | ||
invoke_permission = aws.lambda_.Permission("api-lambda-permission", | ||
action="lambda:invokeFunction", | ||
function=lambda_func, | ||
principal="apigateway.amazonaws.com", | ||
source_arn=deployment.execution_arn.apply( | ||
lambda execution_arn: execution_arn + "*/*"), | ||
) | ||
|
||
# Export the https endpoint of the running Rest API | ||
pulumi.export("endpoint", deployment.invoke_url.apply(lambda url: url + custom_stage_name)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Net; | ||
using System.Threading.Tasks; | ||
|
||
using Amazon.Lambda.Core; | ||
using Amazon.Lambda.APIGatewayEvents; | ||
|
||
using Amazon; | ||
using Amazon.DynamoDBv2; | ||
using Amazon.DynamoDBv2.DataModel; | ||
|
||
using Newtonsoft.Json; | ||
|
||
// Assembly attribute to enable the Lambda function's JSON input to be converted into a .NET class. | ||
[assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.Json.JsonSerializer))] | ||
|
||
namespace app | ||
{ | ||
public class Counter | ||
{ | ||
public string Id { get; set; } | ||
public Int32 Count { get; set; } | ||
} | ||
|
||
public class Functions | ||
{ | ||
// This const is the name of the environment variable that the serverless.template will use to set | ||
// the name of the DynamoDB table used to store blog posts. | ||
const string TABLENAME_ENVIRONMENT_VARIABLE_LOOKUP = "COUNTER_TABLE"; | ||
|
||
IDynamoDBContext DDBContext { get; set; } | ||
|
||
/// <summary> | ||
/// Default constructor that Lambda will invoke. | ||
/// </summary> | ||
public Functions() | ||
{ | ||
// Check to see if a table name was passed in through environment variables and if so | ||
// add the table mapping. | ||
var tableName = System.Environment.GetEnvironmentVariable(TABLENAME_ENVIRONMENT_VARIABLE_LOOKUP); | ||
if(!string.IsNullOrEmpty(tableName)) | ||
{ | ||
AWSConfigsDynamoDB.Context.TypeMappings[typeof(Counter)] = new Amazon.Util.TypeMapping(typeof(Counter), tableName); | ||
} | ||
|
||
var config = new DynamoDBContextConfig { Conversion = DynamoDBEntryConversion.V2 }; | ||
this.DDBContext = new DynamoDBContext(new AmazonDynamoDBClient(), config); | ||
} | ||
|
||
/// <summary> | ||
/// A Lambda function that returns a simple JSON object. | ||
/// </summary> | ||
/// <param name="request"></param> | ||
/// <returns></returns> | ||
public async Task<APIGatewayProxyResponse> GetAsync(APIGatewayProxyRequest request, ILambdaContext context) | ||
{ | ||
context.Logger.LogLine($"Getting count for '{request.Path}'"); | ||
|
||
var counter = await DDBContext.LoadAsync<Counter>(request.Path); | ||
if (counter == null) { | ||
counter = new Counter { Id = request.Path, Count = 1 }; | ||
} | ||
var count = counter.Count++; | ||
await DDBContext.SaveAsync<Counter>(counter); | ||
|
||
context.Logger.LogLine($"Got count {count} for '{request.Path}'"); | ||
|
||
var response = new APIGatewayProxyResponse | ||
{ | ||
StatusCode = (int)HttpStatusCode.OK, | ||
Body = JsonConvert.SerializeObject(new { Path = request.Path, Count = count }), | ||
Headers = new Dictionary<string, string> { { "Content-Type", "application/json" } } | ||
}; | ||
|
||
return response; | ||
} | ||
|
||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
|
||
<PropertyGroup> | ||
<TargetFramework>netcoreapp3.1</TargetFramework> | ||
<GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles> | ||
</PropertyGroup> | ||
|
||
<ItemGroup> | ||
<PackageReference Include="AWSSDK.DynamoDBv2" Version="3.3.5" /> | ||
|
||
<PackageReference Include="Amazon.Lambda.Core" Version="1.0.0" /> | ||
<PackageReference Include="Amazon.Lambda.Serialization.Json" Version="1.1.0" /> | ||
<PackageReference Include="Amazon.Lambda.APIGatewayEvents" Version="1.1.2" /> | ||
|
||
<PackageReference Include="Newtonsoft.Json" Version="10.0.3" /> | ||
</ItemGroup> | ||
|
||
<ItemGroup> | ||
<DotNetCliToolReference Include="Amazon.Lambda.Tools" Version="2.1.1" /> | ||
</ItemGroup> | ||
|
||
</Project> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
grpcio>=1.9.1,!=1.30.0 | ||
pulumi>=2.0.0,<3.0.0 | ||
pulumi-aws>=2.0.0,<3.0.0 |
1 change: 1 addition & 0 deletions
1
aws-ts-serverless-raw/app/.gitignore → aws-ts-serverless-raw/.gitignore
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,3 @@ | ||
/**/obj | ||
/**/bin | ||
/**/node_modules |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.