Skip to content

Commit

Permalink
Upgrade the version of netcoreapp to 3.1 and converted the aws-ts-ser…
Browse files Browse the repository at this point in the history
…verless-raw to a python project
  • Loading branch information
XUANHE ZHOU committed Jun 27, 2020
1 parent 2e982e3 commit d8016c6
Show file tree
Hide file tree
Showing 12 changed files with 278 additions and 6 deletions.
Binary file added .DS_Store
Binary file not shown.
Binary file added aws-py-serverless-raw/.DS_Store
Binary file not shown.
2 changes: 2 additions & 0 deletions aws-py-serverless-raw/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
*.pyc
venv/
6 changes: 6 additions & 0 deletions aws-py-serverless-raw/Pulumi.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
name: aws-py-serverless-raw
runtime:
name: python
options:
virtualenv: venv
description: A minimal Python Pulumi program
160 changes: 160 additions & 0 deletions aws-py-serverless-raw/__main__.py
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=1
)


#####################
## 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))
81 changes: 81 additions & 0 deletions aws-py-serverless-raw/app/Functions.cs
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;
}

}
}
22 changes: 22 additions & 0 deletions aws-py-serverless-raw/app/app.csproj
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>
3 changes: 3 additions & 0 deletions aws-py-serverless-raw/requirements.txt
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
Binary file added aws-ts-serverless-raw/.DS_Store
Binary file not shown.
2 changes: 0 additions & 2 deletions aws-ts-serverless-raw/app/.gitignore

This file was deleted.

2 changes: 1 addition & 1 deletion aws-ts-serverless-raw/app/app.csproj
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework>
<TargetFramework>netcoreapp3.1</TargetFramework>
<GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles>
</PropertyGroup>

Expand Down
6 changes: 3 additions & 3 deletions aws-ts-serverless-raw/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
import * as aws from "@pulumi/aws";
import * as pulumi from "@pulumi/pulumi";

// The location of the built dotnet2.1 application to deploy
const dotNetApplicationPublishFolder = "./app/bin/Debug/netcoreapp2.1/publish";
// The location of the built dotnet3.1 application to deploy
const dotNetApplicationPublishFolder = "./app/bin/Debug/netcoreapp3.1/publish";
const dotNetApplicationEntryPoint = "app::app.Functions::GetAsync";
// The stage name to use for the API Gateway URL
const stageName = "api";
Expand Down Expand Up @@ -54,7 +54,7 @@ const provisionedConcurrentExecutions = config.getNumber("provisionedConcurrency

// Create a Lambda function, using code from the `./app` folder.
const lambda = new aws.lambda.Function("mylambda", {
runtime: aws.lambda.DotnetCore2d1Runtime,
runtime: aws.lambda.DotnetCore3d1Runtime,
code: new pulumi.asset.AssetArchive({
".": new pulumi.asset.FileArchive(dotNetApplicationPublishFolder),
}),
Expand Down

0 comments on commit d8016c6

Please sign in to comment.