diff --git a/.DS_Store b/.DS_Store
new file mode 100644
index 000000000..ceb5e889b
Binary files /dev/null and b/.DS_Store differ
diff --git a/aws-py-serverless-raw/.DS_Store b/aws-py-serverless-raw/.DS_Store
new file mode 100644
index 000000000..46bff2b4a
Binary files /dev/null and b/aws-py-serverless-raw/.DS_Store differ
diff --git a/aws-py-serverless-raw/.gitignore b/aws-py-serverless-raw/.gitignore
new file mode 100644
index 000000000..a3807e5bd
--- /dev/null
+++ b/aws-py-serverless-raw/.gitignore
@@ -0,0 +1,2 @@
+*.pyc
+venv/
diff --git a/aws-py-serverless-raw/Pulumi.yaml b/aws-py-serverless-raw/Pulumi.yaml
new file mode 100644
index 000000000..b831f16b7
--- /dev/null
+++ b/aws-py-serverless-raw/Pulumi.yaml
@@ -0,0 +1,6 @@
+name: aws-py-serverless-raw
+runtime:
+ name: python
+ options:
+ virtualenv: venv
+description: A minimal Python Pulumi program
diff --git a/aws-py-serverless-raw/__main__.py b/aws-py-serverless-raw/__main__.py
new file mode 100644
index 000000000..f48edc563
--- /dev/null
+++ b/aws-py-serverless-raw/__main__.py
@@ -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))
diff --git a/aws-py-serverless-raw/app/Functions.cs b/aws-py-serverless-raw/app/Functions.cs
new file mode 100644
index 000000000..1e6717c1b
--- /dev/null
+++ b/aws-py-serverless-raw/app/Functions.cs
@@ -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; }
+
+ ///
+ /// Default constructor that Lambda will invoke.
+ ///
+ 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);
+ }
+
+ ///
+ /// A Lambda function that returns a simple JSON object.
+ ///
+ ///
+ ///
+ public async Task GetAsync(APIGatewayProxyRequest request, ILambdaContext context)
+ {
+ context.Logger.LogLine($"Getting count for '{request.Path}'");
+
+ var counter = await DDBContext.LoadAsync(request.Path);
+ if (counter == null) {
+ counter = new Counter { Id = request.Path, Count = 1 };
+ }
+ var count = counter.Count++;
+ await DDBContext.SaveAsync(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 { { "Content-Type", "application/json" } }
+ };
+
+ return response;
+ }
+
+ }
+}
diff --git a/aws-py-serverless-raw/app/app.csproj b/aws-py-serverless-raw/app/app.csproj
new file mode 100644
index 000000000..b18223b69
--- /dev/null
+++ b/aws-py-serverless-raw/app/app.csproj
@@ -0,0 +1,22 @@
+
+
+
+ netcoreapp3.1
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/aws-py-serverless-raw/requirements.txt b/aws-py-serverless-raw/requirements.txt
new file mode 100644
index 000000000..e1180f4ab
--- /dev/null
+++ b/aws-py-serverless-raw/requirements.txt
@@ -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
diff --git a/aws-ts-serverless-raw/.DS_Store b/aws-ts-serverless-raw/.DS_Store
new file mode 100644
index 000000000..b782cafbf
Binary files /dev/null and b/aws-ts-serverless-raw/.DS_Store differ
diff --git a/aws-ts-serverless-raw/app/.gitignore b/aws-ts-serverless-raw/app/.gitignore
deleted file mode 100644
index 0181616c5..000000000
--- a/aws-ts-serverless-raw/app/.gitignore
+++ /dev/null
@@ -1,2 +0,0 @@
-/**/obj
-/**/bin
diff --git a/aws-ts-serverless-raw/app/app.csproj b/aws-ts-serverless-raw/app/app.csproj
index 97d54097e..b18223b69 100644
--- a/aws-ts-serverless-raw/app/app.csproj
+++ b/aws-ts-serverless-raw/app/app.csproj
@@ -1,7 +1,7 @@
- netcoreapp2.1
+ netcoreapp3.1
true
diff --git a/aws-ts-serverless-raw/index.ts b/aws-ts-serverless-raw/index.ts
index 75b3c8c1e..c9779107e 100644
--- a/aws-ts-serverless-raw/index.ts
+++ b/aws-ts-serverless-raw/index.ts
@@ -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";
@@ -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),
}),