Skip to content

Commit

Permalink
fix: Impose a 127 character limit on the Lambda function handler when…
Browse files Browse the repository at this point in the history
… the package type is set to zip (#1812)

Addresses #1778
  • Loading branch information
96malhar authored Sep 23, 2024
1 parent a3a8d44 commit 63152f3
Show file tree
Hide file tree
Showing 9 changed files with 95 additions and 26 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
; Shipped analyzer releases
; https://github.com/dotnet/roslyn-analyzers/blob/master/src/Microsoft.CodeAnalysis.Analyzers/ReleaseTrackingAnalyzers.Help.md

## Release 1.5.1
### New Rules

Rule ID | Category | Severity | Notes
--------|----------|----------|-------
AWSLambda0118 | AWSLambdaCSharpGenerator | Error | Maximum Handler Length Exceeded

## Release 1.5.0
### New Rules

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -138,5 +138,12 @@ public static class DiagnosticDescriptors
category: "AWSLambdaCSharpGenerator",
DiagnosticSeverity.Error,
isEnabledByDefault: true);

public static readonly DiagnosticDescriptor MaximumHandlerLengthExceeded = new DiagnosticDescriptor(id: "AWSLambda0118",
title: "Maximum Handler Length Exceeded",
messageFormat: "The handler string '{0}' exceeds the maximum length of 127 characters. Please trim down your project namespace, class name or method name to stay within the character limit.",
category: "AWSLambdaCSharpGenerator",
DiagnosticSeverity.Error,
isEnabledByDefault: true);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,15 @@ internal static bool ValidateFunction(GeneratorExecutionContext context, IMethod
diagnostics.Add(Diagnostic.Create(DiagnosticDescriptors.InvalidResourceName, methodLocation));
}

// Check the handler length does not exceed 127 characters when the package type is set to zip
// The official AWS docs state a 128 character limit on the Lambda handler. However, there is an open issue where the last character is stripped off
// when the handler is exactly 128 characters long. Hence, we are enforcing a 127 character limit.
// https://github.com/aws/aws-lambda-dotnet/issues/1642
if (lambdaFunctionModel.PackageType == LambdaPackageType.Zip && lambdaFunctionModel.Handler.Length > 127)
{
diagnostics.Add(Diagnostic.Create(DiagnosticDescriptors.MaximumHandlerLengthExceeded, methodLocation, lambdaFunctionModel.Handler));
}

// Check for Serializer attribute
if (!lambdaMethodSymbol.ContainingAssembly.HasAttribute(context, TypeFullNames.LambdaSerializerAttribute))
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,15 +35,18 @@
}
},
"Properties": {
"Runtime": "dotnet6",
"CodeUri": ".",
"MemorySize": 512,
"Timeout": 30,
"Policies": [
"AWSLambdaBasicExecutionRole"
],
"PackageType": "Zip",
"Handler": "TestProject::TestServerlessApp.SQSEventExamples.ValidSQSEvents_ProcessMessages_Generated::ProcessMessages",
"PackageType": "Image",
"ImageUri": ".",
"ImageConfig": {
"Command": [
"TestProject::TestServerlessApp.SQSEventExamples.ValidSQSEvents_ProcessMessages_Generated::ProcessMessages"
]
},
"Events": {
"queue1": {
"Type": "SQS",
Expand Down Expand Up @@ -109,15 +112,18 @@
}
},
"Properties": {
"Runtime": "dotnet6",
"CodeUri": ".",
"MemorySize": 512,
"Timeout": 30,
"Policies": [
"AWSLambdaBasicExecutionRole"
],
"PackageType": "Zip",
"Handler": "TestProject::TestServerlessApp.SQSEventExamples.ValidSQSEvents_ProcessMessagesWithBatchFailureReporting_Generated::ProcessMessagesWithBatchFailureReporting",
"PackageType": "Image",
"ImageUri": ".",
"ImageConfig": {
"Command": [
"TestProject::TestServerlessApp.SQSEventExamples.ValidSQSEvents_ProcessMessagesWithBatchFailureReporting_Generated::ProcessMessagesWithBatchFailureReporting"
]
},
"Events": {
"queue3": {
"Type": "SQS",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1330,6 +1330,31 @@ public async Task VerifyValidSQSEvents()
}.RunAsync();
}

[Fact]
public async Task ExceededMaximumHandlerLength()
{
await new VerifyCS.Test
{
TestState =
{
Sources =
{
(Path.Combine("TestServerlessApp", "PlaceholderClass.cs"), await File.ReadAllTextAsync(Path.Combine("TestServerlessApp", "PlaceholderClass.cs"))),
(Path.Combine("TestServerlessApp", "ExceededMaximumHandlerLength.cs"), await File.ReadAllTextAsync(Path.Combine("TestServerlessApp", "ExceededMaximumHandlerLength.cs.error"))),
(Path.Combine("Amazon.Lambda.Annotations", "LambdaFunctionAttribute.cs"), await File.ReadAllTextAsync(Path.Combine("Amazon.Lambda.Annotations", "LambdaFunctionAttribute.cs"))),
(Path.Combine("TestServerlessApp", "AssemblyAttributes.cs"), await File.ReadAllTextAsync(Path.Combine("TestServerlessApp", "AssemblyAttributes.cs"))),
},
ExpectedDiagnostics =
{
DiagnosticResult
.CompilerError("AWSLambda0118")
.WithSpan($"TestServerlessApp{Path.DirectorySeparatorChar}ExceededMaximumHandlerLength.cs", 9, 9, 13, 10)
.WithArguments("TestProject::TestServerlessApp.ExceededMaximumHandlerLength_SayHelloXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX_Generated::SayHelloXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX")
},
}
}.RunAsync();
}

public void Dispose()
{
File.Delete(Path.Combine("TestServerlessApp", "serverless.template"));
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
using System;
using Amazon.Lambda.Annotations;

namespace TestServerlessApp
{
public class ExceededMaximumHandlerLength
{
// This fails because generated handler is longer than 127 characters
[LambdaFunction]
public string SayHelloXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX()
{
return "Hello, World!";
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,72 +12,72 @@ namespace TestServerlessApp.SQSEventExamples

public class InvalidSQSEvents
{
[LambdaFunction]
[LambdaFunction(PackageType = LambdaPackageType.Image)]
[SQSEvent("@testQueue", BatchSize = 0, MaximumBatchingWindowInSeconds = 302, MaximumConcurrency = 1)]
public void ProcessMessageWithInvalidSQSEventAttributes(SQSEvent evnt)
{
Console.WriteLine($"Event processed: {evnt}");
}

[LambdaFunction]
[LambdaFunction(PackageType = LambdaPackageType.Image)]
[SQSEvent("@testQueue")]
public void ProcessMessageWithInvalidParameters(SQSEvent evnt, bool invalidParameter1, int invalidParameter2)
{
Console.WriteLine($"Event processed: {evnt}");
}

[LambdaFunction]
[LambdaFunction(PackageType = LambdaPackageType.Image)]
[SQSEvent("@testQueue")]
public bool ProcessMessageWithInvalidReturnType(SQSEvent evnt)
{
Console.WriteLine($"Event processed: {evnt}");
return true;
}

[LambdaFunction]
[LambdaFunction(PackageType = LambdaPackageType.Image)]
[RestApi(LambdaHttpMethod.Get, "/")]
[SQSEvent("@testQueue")]
public void ProcessMessageWithMultipleEventTypes(SQSEvent evnt)
{
Console.WriteLine($"Event processed: {evnt}");
}

[LambdaFunction]
[LambdaFunction(PackageType = LambdaPackageType.Image)]
[SQSEvent("test-queue")]
public void ProcessMessageWithInvalidQueueArn(SQSEvent evnt)
{
Console.WriteLine($"Event processed: {evnt}");
}

[LambdaFunction]
[LambdaFunction(PackageType = LambdaPackageType.Image)]
[SQSEvent("@testQueue", ResourceName = "sqs-event-source")]
public void ProcessMessageWithInvalidResourceName(SQSEvent evnt)
{
Console.WriteLine($"Event processed: {evnt}");
}

[LambdaFunction]
[LambdaFunction(PackageType = LambdaPackageType.Image)]
[SQSEvent("@testQueue", ResourceName = "")]
public void ProcessMessageWithEmptyResourceName(SQSEvent evnt)
{
Console.WriteLine($"Event processed: {evnt}");
}

[LambdaFunction]
[LambdaFunction(PackageType = LambdaPackageType.Image)]
[SQSEvent("@testQueue", BatchSize = 100)]
public void ProcessMessageWithMaximumBatchingWindowInSecondsNotSpecified(SQSEvent evnt)
{
Console.WriteLine($"Event processed: {evnt}");
}

[LambdaFunction]
[LambdaFunction(PackageType = LambdaPackageType.Image)]
[SQSEvent("@testQueue", BatchSize = 100, MaximumBatchingWindowInSeconds = 0)]
public void ProcessMessageWithMaximumBatchingWindowInSecondsLessThanOne(SQSEvent evnt)
{
Console.WriteLine($"Event processed: {evnt}");
}

[LambdaFunction]
[LambdaFunction(PackageType = LambdaPackageType.Image)]
[SQSEvent("arn:aws:sqs:us-east-2:444455556666:test-queue.fifo", BatchSize = 100, MaximumBatchingWindowInSeconds = 5)]
public void ProcessMessageWithFifoQueue(SQSEvent evnt)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ namespace TestServerlessApp.SQSEventExamples

public class ValidSQSEvents
{
[LambdaFunction]
[LambdaFunction(PackageType = LambdaPackageType.Image)]
[SQSEvent("arn:aws:sqs:us-east-2:444455556666:queue1", BatchSize = 50, MaximumBatchingWindowInSeconds = 2, MaximumConcurrency = 30, Filters = "My-Filter-1; My-Filter-2")]
[SQSEvent("arn:aws:sqs:us-east-2:444455556666:queue2", MaximumBatchingWindowInSeconds = 5, Enabled = false)]
[SQSEvent("arn:aws:sqs:us-east-2:444455556666:my-queue")]
Expand All @@ -22,7 +22,7 @@ namespace TestServerlessApp.SQSEventExamples
Console.WriteLine($"Event processed: {evnt}");
}

[LambdaFunction]
[LambdaFunction(PackageType = LambdaPackageType.Image)]
[SQSEvent("arn:aws:sqs:us-east-2:444455556666:queue3")]
public async Task<SQSBatchResponse> ProcessMessagesWithBatchFailureReporting(SQSEvent evnt)
{
Expand Down
12 changes: 6 additions & 6 deletions Libraries/test/TestServerlessApp/serverless.template
Original file line number Diff line number Diff line change
Expand Up @@ -913,12 +913,6 @@
"TestQueueEvent": {
"Type": "SQS",
"Properties": {
"Queue": {
"Fn::GetAtt": [
"TestQueue",
"Arn"
]
},
"BatchSize": 50,
"FilterCriteria": {
"Filters": [
Expand All @@ -933,6 +927,12 @@
"MaximumBatchingWindowInSeconds": 5,
"ScalingConfig": {
"MaximumConcurrency": 5
},
"Queue": {
"Fn::GetAtt": [
"TestQueue",
"Arn"
]
}
}
}
Expand Down

0 comments on commit 63152f3

Please sign in to comment.