AWS Developer Tools Blog
Deploying .NET Core AWS Lambda Functions from the Command Line
In previous posts about our .NET Core support with AWS Lambda, we’ve shown how you can create Lambda functions and serverless applications with Visual Studio. But one of the most exciting things about .NET Core is its cross-platform support with the new command line interface (CLI) named dotnet. To help you develop Lambda functions outside of Visual Studio, we’ve released the Amazon.Lambda.Tools NuGet package that integrates with the dotnet CLI.
We released Amazon.Lambda.Tools as a preview with our initial release of .NET Core on Lambda. We kept it in preview while .NET Core tooling, including the dotnet CLI, was in preview. With the recent release of Visual Studio 2017, the dotnet CLI and our integration with it is now marked as generally available (GA). If you’re still using preview versions of the dotnet CLI and the pre-Visual Studio 2017 project structure, the GA release of Amazon.Lambda.Tools will still work for those projects.
.NET Core Project Structure
When .NET Core was originally released last summer, you would define a project in a JSON file named project.json. At that time, it was announced that this was temporary, that .NET Core was moving to be in line with other .NET projects and would be based on the msbuild XML format, and that each project would contain a .csproj file. As part of the GA release of the dotnet CLI tooling, the release includes the switch to the msbuild format.
Amazon.Lambda.Tools Registration
If you create an AWS Lambda project in Visual Studio, the command line integration is set up automatically so that you can easily transition from Visual Studio to the command line. If you inspect a project created in Visual Studio 2017, you’ll notice a DotNetCliToolReference for the Amazon.Lambda.Tools NuGet package.
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp1.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Amazon.Lambda.Core" Version="1.0.0" />
<PackageReference Include="Amazon.Lambda.Serialization.Json" Version="1.0.1" />
</ItemGroup>
<ItemGroup>
<DotNetCliToolReference Include="Amazon.Lambda.Tools" Version="1.4.0" />
</ItemGroup>
</Project>
In Visual Studio 2015, which uses the older project.json format, the Amazon.Lambda.Tools package is declared as a build dependency and is also registered in the tools section.
{
"version": "1.0.0-*",
"buildOptions": {
},
"dependencies": {
"Microsoft.NETCore.App": {
"type": "platform",
"version": "1.0.0"
},
"Amazon.Lambda.Core": "1.0.0*",
"Amazon.Lambda.Serialization.Json": "1.0.1",
"Amazon.Lambda.Tools" : {
"type" :"build",
"version":"1.4.0 "
}
},
"tools": {
"Amazon.Lambda.Tools" : "1.4.0 "
},
"frameworks": {
"netcoreapp1.0": {
"imports": "dnxcore50"
}
}
}
Adding to an Existing Project
The Amazon.Lambda.Tools NuGet package is marked as DotNetCliTool package type. Right now Visual Studio 2017 doesn’t understand the new package type. If you attempt to add the NuGet package through Visual Studio’s Manage NuGet Packages dialog it won’t be able to add the reference. Till Visual Studio 2017 is updated you will need to manually add the DotNetCliToolReference in the csproj file.
Deploying Lambda Functions
All the tooling we developed for Visual Studio to deploy Lambda functions originated in the Amazon.Lambda.Tools package. That means all the deployment features you use inside Visual Studio you can also do from the command line.
To get started, in a command window navigate to a project you created in Visual Studio. To see the available commands, enter dotnet lambda help.
C:\BlogContent\BlogExample\BlogExample> dotnet lambda help
AWS Lambda Tools for .NET Core functions
Project Home: https://github.com/aws/aws-lambda-dotnet
Commands to deploy and manage AWS Lambda functions:
deploy-function Command to deploy the project to AWS Lambda
invoke-function Command to invoke a function in Lambda with an optional input
list-functions Command to list all your Lambda functions
delete-function Command to delete an AWS Lambda function
get-function-config Command to get the current runtime configuration for a Lambda function
update-function-config Command to update the runtime configuration for a Lambda function
Commands to deploy and manage AWS Serverless applications using AWS CloudFormation:
deploy-serverless Command to deploy an AWS Serverless application
list-serverless Command to list all your AWS Serverless applications
delete-serverless Command to delete an AWS Serverless application
Other Commands:
package Command to package a Lambda project into a zip file ready for deployment
To get help on individual commands execute:
dotnet lambda help <command>
By using the dotnet lambda command you have access to a collection of commands to manage Lambda functions and serverless applications. There is also a package command that packages your project into a .zip file, ready for deployment. This can be useful for CI systems.
To see help for an individual command, type dotnet lambda help followed by the command name; for example, dotnet lambda help deploy-function.
C:\BlogContent\BlogExample\BlogExample> dotnet lambda help deploy-function
AWS Lambda Tools for .NET Core functions
Project Home: https://github.com/aws/aws-lambda-dotnet
deploy-function:
Command to deploy the project to AWS Lambda
dotnet lambda deploy-function [arguments] [options]
Arguments:
<FUNCTION-NAME> The name of the function to deploy
Options:
--region The region to connect to AWS services, if not set region will be detected from the environment (Default Value: us-east-2)
--profile Profile to use to look up AWS credentials, if not set environment credentials will be used (Default Value: normj+vpc)
--profile-location Optional override to the search location for Profiles, points at a shared credentials file
-pl | --project-location The location of the project, if not set the current directory will be assumed
-cfg | --config-file Configuration file storing default values for command line arguments. Default is aws-lambda-tools-defaults.json
-c | --configuration Configuration to build with, for example Release or Debug (Default Value: Release)
-f | --framework Target framework to compile, for example netcoreapp1.0 (Default Value: netcoreapp1.0)
-pac | --package Application package to use for deployment, skips building the project
-fn | --function-name AWS Lambda function name
-fd | --function-description AWS Lambda function description
-fp | --function-publish Publish a new version as an atomic operation
-fh | --function-handler Handler for the function <assembly>::<type>::<method> (Default Value: BlogExample::BlogExample.Function::FunctionHandler)
-fms | --function-memory-size The amount of memory, in MB, your Lambda function is given (Default Value: 256)
-frole | --function-role The IAM role that Lambda assumes when it executes your function
-ft | --function-timeout The function execution timeout in seconds (Default Value: 30)
-frun | --function-runtime The runtime environment for the Lambda function (Default Value: dotnetcore1.0)
-fsub | --function-subnets Comma delimited list of subnet ids if your function references resources in a VPC
-fsec | --function-security-groups Comma delimited list of security group ids if your function references resources in a VPC
-dlta | --dead-letter-target-arn Target ARN of an SNS topic or SQS Queue for the Dead Letter Queue
-ev | --environment-variables Environment variables set for the function. Format is <key1>=<value1>;<key2>=<value2>
-kk | --kms-key KMS Key ARN of a customer key used to encrypt the function's environment variables
-sb | --s3-bucket S3 bucket to upload the build output
-sp | --s3-prefix S3 prefix for for the build output
-pcfg | --persist-config-file If true the arguments used for a successful deployment are persisted to a config file. Default config file is aws-lambda-tools-defaults.json
C:\BlogContent\BlogExample\BlogExample>
As you can see, you can set many options with this command. This is where the aws-lambda-tools-defaults.json file, which is created as part of your project, comes in handy. You can set the options in this file, which is read by the Lambda tooling by default. The project templates created in Visual Studio set many of these fields with default values.
{
"profile":"default",
"region" : "us-east-2",
"configuration" : "Release",
"framework" : "netcoreapp1.0",
"function-runtime":"dotnetcore1.0",
"function-memory-size" : 256,
"function-timeout" : 30,
"function-handler" : "BlogExample::BlogExample.Function::FunctionHandler"
}
When you use this aws-lambda-tools-default.json file, the only things left that the Lambda tooling needs to deploy the function are the name of the Lambda function and the IAM role. You do this by using the following command:
dotnet lambda deploy-function TheFunction --function-role TestRole
C:\BlogContent\BlogExample\BlogExample> dotnet lambda deploy-function TheFunction --function-role TestRole
Executing publish command
Deleted previous publish folder
... invoking 'dotnet publish', working folder 'C:\BlogContent\BlogExample\BlogExample\bin\Release\netcoreapp1.0\publish'
... publish: Microsoft (R) Build Engine version 15.1.548.43366
... publish: Copyright (C) Microsoft Corporation. All rights reserved.
... publish: BlogExample -> C:\BlogContent\BlogExample\BlogExample\bin\Release\netcoreapp1.0\BlogExample.dll
Zipping publish folder C:\BlogContent\BlogExample\BlogExample\bin\Release\netcoreapp1.0\publish to C:\BlogContent\BlogExample\BlogExample\bin\Release\netcoreapp1.0\BlogExample.zip
... zipping: Amazon.Lambda.Core.dll
... zipping: Amazon.Lambda.Serialization.Json.dll
... zipping: BlogExample.deps.json
... zipping: BlogExample.dll
... zipping: BlogExample.pdb
... zipping: Newtonsoft.Json.dll
... zipping: System.Runtime.Serialization.Primitives.dll
Creating new Lambda function TheFunction
New Lambda function created
C:\BlogContent\BlogExample\BlogExample>
You can also pass an alternative file that contains option defaults by using the –config-file option. This enables you to reuse multiple Lambda configurations.
“dotnet publish” vs “dotnet lambda” Commands
Using the Amazon.Lambda.Tools package is the preferred way to deploy functions to Lambda from the command line versus using the dotnet publish command, zipping that output folder, and sending the zip file to Lambda. The Lambda tooling looks at the publish folder and removes any duplicate native dependency in it, which reduces the size of your Lambda function. For example, if you reference the SQL Server client NuGet package, System.Data.SqlClient, the Lambda tooling produces a package file that is about 1 MB smaller than the zipped publish folder from dotnet publish. It also reworks the layout of native dependencies to ensure that the Lambda service finds the native dependencies.
Summary
We hope the Amazon.Lambda.Tools package helps you with the transition from working in Visual Studio to working in the command line to script and automate your deployments. Let us know what you think on our GitHub repository, and what you’d like to see us add to the tooling.