Aws-cdk: Missing nuGet packages after deploying Web Serverless with CDK in C#

Created on 8 Oct 2019  路  9Comments  路  Source: aws/aws-cdk


I created a single web serverless application using the default template for the AWS toolkit.
I created a CDK project to deploy it with a simple lambda function and the LambdaRestApi.

When deploying with cdk everything goes fine, the asset file is created and the stack deploys without any problem.

When I try to browse the url returned in output, I get {"message": "Internal server error"}. Checking the logs at CloudWatch the error is totally unexpected:

`

Error:
An assembly specified in the application dependencies manifest (CdkMissingLib.deps.json) was not found:
package: 'Amazon.Lambda.APIGatewayEvents', version: '1.2.0'
path: 'lib/netstandard2.0/Amazon.Lambda.APIGatewayEvents.dll'
START RequestId: 938d4091-a8d2-4e5c-a4eb-3ffbb69b090a Version: $LATEST
Failed to execute the Lambda function. The dotnet CLI failed to start with the provided deployment package. Please check CloudWatch logs for this Lambda function to get detailed information about this failure.: LambdaException

END RequestId: 938d4091-a8d2-4e5c-a4eb-3ffbb69b090a
REPORT RequestId: 938d4091-a8d2-4e5c-a4eb-3ffbb69b090a Duration: 457.96 ms Billed Duration: 500 ms Memory Size: 128 MB Max Memory Used: 64 MB Init Duration: 239.59 ms

`

The package it's complaining is not even used in my solution. Furthermore, the solution where I found this problem was complaining about another nuget package "AWSSDK.Core" that WAS referenced in the solution...

Reproduction Steps

This is how I define the stack for CDK:

```
public class CdkMissingLibInfraStack : Stack
{
public CdkMissingLibInfraStack(Construct parent, string id, IStackProps props) : base(parent, id, props)
{

        var lambdaFunction = new Function(this, "webapi-function",
            new FunctionProps
            {
                Code = Code.FromAsset(@"C:\Users\joanv\Source\Repos\CdkMissingLib\CdkMissingLib\bin\Debug\netcoreapp2.1"),
                Handler = "CdkMissingLib::CdkMissingLib.LambdaEntryPoint::FunctionHandlerAsync",
                Runtime = Runtime.DOTNET_CORE_2_1,
                Timeout = Duration.Seconds(30),
                MemorySize = 128
            }
        );

        var api = new LambdaRestApi(this, "webapi-function-api", new LambdaRestApiProps
        {
            Handler = lambdaFunction
        });

    }
}

```

Error Log

Error:
An assembly specified in the application dependencies manifest (CdkMissingLib.deps.json) was not found:
package: 'Amazon.Lambda.APIGatewayEvents', version: '1.2.0'
path: 'lib/netstandard2.0/Amazon.Lambda.APIGatewayEvents.dll'
START RequestId: 938d4091-a8d2-4e5c-a4eb-3ffbb69b090a Version: $LATEST
Failed to execute the Lambda function. The dotnet CLI failed to start with the provided deployment package. Please check CloudWatch logs for this Lambda function to get detailed information about this failure.: LambdaException

END RequestId: 938d4091-a8d2-4e5c-a4eb-3ffbb69b090a
REPORT RequestId: 938d4091-a8d2-4e5c-a4eb-3ffbb69b090a Duration: 457.96 ms Billed Duration: 500 ms Memory Size: 128 MB Max Memory Used: 64 MB Init Duration: 239.59 ms

Environment

  • CLI Version : 11.12.0 (build 923055e)
  • Framework Version: 2.1
  • OS : Windows
  • Language : C# .Net Core

This is :bug: Bug Report

@aws-cdassets guidance languagdotnet

Most helpful comment

Also please be aware you will need to build your .NET project before running the CDK deploy on it. CDK will not build for you.

All 9 comments

@RomainMuller Could you have a look at this please?

From the name of this package: Amazon.Lambda.APIGatewayEvents I'm divining that it contains type definitions for Lambda events. In this case, probably API gateway event definitions. Does that mean anything to you?

I've heard from @javydekoning that if you package the Lambda by hand, everything works as expected.

  • How does packaging by hand work? Is that an action in your IDE, or are you zipping up a directory?
  • What's the difference between the 2 zips that get created that way? You can find out by running cdk deploy -v, noting the S3 address it will upload the asset zip to, downloading it, and comparing the 2 zips.

On a Unix-like, unzip -l ZIPFILE will tell you the contents. On Windows, I guess you extract it to a directory and run dir /s /b.

Pay particular attention to the CdkMissingLib.deps.json file in both archives and see if they are different.

Also please be aware you will need to build your .NET project before running the CDK deploy on it. CDK will not build for you.

The problem here is that you're bundling the "build output" of your .NET project as your Lambda runtime, and this does _not_ contain any of your dependencies.

The CDK assets are "not smart" in that they cannot bring in the dependencies from your code, etc... So you have to bundle a "self-sufficient" assembly (or bring in the required dependencies via a Lambda layer, or something like that).

Also please be aware you will need to _build_ your .NET project before running the CDK deploy on it. CDK will not build for you.

Yup already know that ... but I thought CDK would act like the AWS tool for dotnet.

The problem here is that you're bundling the "build output" of your .NET project as your Lambda runtime, and this does _not_ contain any of your dependencies.

The CDK assets are "not smart" in that they cannot bring in the dependencies from your code, etc... So you have to bundle a "self-sufficient" assembly (or bring in the required dependencies via a Lambda layer, or something like that).

Ok, so what would be the best way?

I can create the artifact .zip file using "dotnet lambda package" (it's an amazon plugin you can install for dotnet) and then the zip is correct.

Can I use that .zip as Code.FromAsset() ?? or it must be a folder ?

If that's possible then it's easy just to create a small Powershell script to package the .zip and then run the cdk deploy...

Does this sound ok 驴?

I believe projects in Visual Studio can be configured to copy in dependencies to the output directory. But I'm unsure of where this dependency is coming from, and if you don't know either, then I'm afraid we're a little stuck on a "nice" way.

Can I use that .zip as Code.FromAsset() ??

Yes.

Does this sound ok 驴?

That sounds fine.

@LechuckThePirate that sounds like a solid plan indeed. The dotnet lambda package command will build a correct Lambda deployment bundle that includes all the necessary dependencies, ...

The fromAsset function can be pointed either to a directory (contents will be zip'd) or to a .zip file.

Fixed guys... thanks for your help... here's the final "deploy.ps1" script I created .. it works like a charm:

# Input Parameters
param (
    $localFolder = "C:\Users\joanv\Source\Repos\CdkMissingLib"
);


# Helpers
function Write-ColorOutput($ForegroundColor)
{
    # save the current color
    $fc = $host.UI.RawUI.ForegroundColor

    # set the new color
    $host.UI.RawUI.ForegroundColor = $ForegroundColor

    # output
    if ($args) {
        Write-Output $args
    }
    else {
        $input | Write-Output
    }

    # restore the original color
    $host.UI.RawUI.ForegroundColor = $fc
}

# Building & Packaging
Write-ColorOutput "cyan" "Building Solution..."
Set-Location $localFolder
dotnet build .\CdkMissingLib.sln -c Release

if ($?) 
{
    Write-ColorOutput "cyan" "  >> Packaging artifacts..."
    Set-Location .\CdkMissingLib
    dotnet lambda package -f netcoreapp2.1 -c Release 
}

Set-Location $localFolder

if ($?) {
    # Deploying to AWS
    Write-ColorOutput "cyan" "Deploying to AWS..."
    cdk deploy 
}

if ($?) {
    # End
    Write-ColorOutput "green" "Done!"
}

if (!$?) {
    Write-ColorOutput "red" "There was an error in the process ..."
}
Set-Location $localFolder

In my CDK project I just changed the Code.FromAsset to point to the packaged ZIP:

image

This did the trick... the website is now working.

Going to apply this to the real project now... Thanks again for your help

Was this page helpful?
0 / 5 - 0 ratings