├── .config └── dotnet-tools.json ├── .editorconfig ├── .github ├── FUNDING.yml ├── auto_assign.yml ├── releases │ ├── v0.1.7.md │ ├── v0.1.8.md │ ├── v0.1.9.md │ ├── v0.10.0-beta1.md │ ├── v0.10.0-beta2.md │ ├── v0.10.0-beta3.md │ ├── v0.2.0.md │ ├── v0.2.1.md │ ├── v0.3.0-beta1.md │ ├── v0.3.0-beta2.md │ ├── v0.3.0-beta3.md │ ├── v0.3.0.md │ ├── v0.4.0-beta1.md │ ├── v0.4.0-beta2.md │ ├── v0.4.0-beta3.md │ ├── v0.4.0.md │ ├── v0.5.0-beta1.md │ ├── v0.5.0-beta2.md │ ├── v0.5.0-beta3.md │ ├── v0.5.0.md │ ├── v0.6.0-beta1.md │ ├── v0.6.0-beta2.md │ ├── v0.6.0-beta3.md │ ├── v0.6.0-beta4.md │ ├── v0.6.0.md │ ├── v0.7.0-beta1.md │ ├── v0.7.0-beta2.md │ ├── v0.7.0-beta3.md │ ├── v0.7.0-beta4.md │ ├── v0.7.0.md │ ├── v0.8.0-beta1.md │ ├── v0.8.0-beta2.md │ ├── v0.8.0-beta3.md │ ├── v0.8.0-beta4.md │ ├── v0.8.0-beta5.md │ ├── v0.8.0.md │ ├── v0.8.1.md │ ├── v0.8.2.md │ ├── v0.8.3.md │ ├── v0.8.4.md │ ├── v0.8.5.md │ ├── v0.9.0-beta1.md │ ├── v0.9.0-beta2.md │ ├── v0.9.0-beta3.md │ ├── v0.9.0-beta4.md │ ├── v0.9.0-beta5.md │ ├── v0.9.0.md │ ├── v0.9.1.md │ └── v0.9.2.md └── workflows │ ├── assign-prs.yml │ ├── ci.yml │ └── codeql-analysis.yml ├── .gitignore ├── .vscode ├── csharp.code-snippets ├── extensions.json ├── launch.json ├── settings.json └── tasks.json ├── CONTRIBUTING.md ├── Directory.Build.props ├── LICENSE.txt ├── Makefile ├── README.md ├── SECURITY.md ├── after.lambdajection.sln.targets ├── codecov.yml ├── examples ├── AwsClientFactories │ ├── .gitignore │ ├── AwsClientFactories.csproj │ ├── Handler.cs │ ├── README.md │ ├── Request.cs │ ├── Startup.cs │ ├── cloudformation.config.json │ └── cloudformation.template.yml ├── CustomConfiguration │ ├── Config.cs │ ├── ConfigFactory.cs │ ├── CustomConfiguration.csproj │ ├── Handler.cs │ ├── README.md │ ├── Startup.cs │ ├── appsettings.json │ ├── cloudformation.config.json │ └── cloudformation.template.yml ├── CustomResource │ ├── CustomResource.csproj │ ├── Options.cs │ ├── PasswordGenerator.cs │ ├── README.md │ ├── Request.cs │ ├── Response.cs │ ├── Startup.cs │ ├── cloudformation.config.json │ └── cloudformation.template.yml ├── CustomRuntime │ ├── CustomRuntime.csproj │ ├── Handler.cs │ ├── Startup.cs │ ├── cloudformation.config.json │ └── cloudformation.template.yml ├── Directory.Build.props ├── Directory.Build.targets ├── EncryptedOptions │ ├── .gitignore │ ├── EncryptedOptions.csproj │ ├── Handler.cs │ ├── Options.cs │ ├── README.md │ ├── Startup.cs │ ├── cloudformation.config.json │ └── cloudformation.template.yml ├── SnsHandler │ ├── Handler.cs │ ├── Response.cs │ ├── SnsHandler.csproj │ ├── Startup.cs │ ├── cloudformation.config.json │ └── cloudformation.template.yml └── examples.sln ├── global.json ├── lambdajection.sln ├── nuget.config ├── omnisharp.json ├── renovate.json ├── src ├── Attributes │ ├── Attributes.csproj │ ├── CustomResourceProviderAttribute.cs │ ├── LambdaAttribute.cs │ ├── LambdaOptionsAttribute.cs │ ├── SnsEventHandlerAttribute.cs │ ├── UpdateRequiresReplacementAttribute.cs │ └── packages.lock.json ├── Core │ ├── Core.csproj │ ├── DefaultHttpClient.cs │ ├── DefaultLambdaHost.cs │ ├── Exceptions │ │ └── InvalidLambdaParameterException.cs │ ├── IAwsFactory.cs │ ├── IHttpClient.cs │ ├── ILambda.cs │ ├── ILambdaConfigFactory.cs │ ├── ILambdaConfigurator.cs │ ├── ILambdaInitializationService.cs │ ├── ILambdaStartup.cs │ ├── LambdaConfigFactory.cs │ ├── LambdaHostBase.cs │ ├── LambdaHostBuilder.cs │ ├── LambdaScope.cs │ ├── LambdaServiceCollectionExtensions.cs │ ├── Serialization │ │ ├── ISerializer.cs │ │ ├── JsonSerializer.cs │ │ ├── JsonSerializerSettings.cs │ │ ├── StringConverter.cs │ │ └── StringConverterFactory.cs │ ├── build │ │ └── Lambdajection.Core.props │ └── packages.lock.json ├── CustomResource.BuildTime │ ├── CustomResource.BuildTime.csproj │ ├── RequiresReplacementGenerator.cs │ ├── build │ │ └── Lambdajection.CustomResource.BuildTime.props │ └── packages.lock.json ├── CustomResource │ ├── CustomResource.csproj │ ├── CustomResourceLambdaHost.cs │ ├── CustomResourceRequest.cs │ ├── CustomResourceRequestType.cs │ ├── CustomResourceRequest{TResourceProperties}.cs │ ├── CustomResourceResponse.cs │ ├── CustomResourceResponseStatus.cs │ ├── CustomResourceResponseStatusConverter.cs │ ├── ICustomResourceOutputData.cs │ ├── ICustomResourceProvider.cs │ └── packages.lock.json ├── Encryption │ ├── DefaultDecryptionService.cs │ ├── EncryptedAttribute.cs │ ├── Encryption.csproj │ ├── IDecryptionService.cs │ ├── build │ │ └── Lambdajection.Encryption.props │ └── packages.lock.json ├── Framework.BuildTime │ ├── AnalyzerResults.cs │ ├── Framework.BuildTime.csproj │ ├── GeneratedMethodInfo.cs │ ├── GenerationContext.cs │ ├── GenerationFailureException.cs │ ├── GenerationSettings.cs │ ├── IMemberGenerator.cs │ ├── Utils │ │ └── TypeUtils.cs │ ├── build │ │ └── Lambdajection.Framework.BuildTime.props │ └── packages.lock.json ├── Framework │ ├── Framework.csproj │ ├── GeneratedAttribute.cs │ ├── Internal │ │ └── IsExternalInit.cs │ ├── LambdaHostAttribute.cs │ ├── LambdaInterfaceAttribute.cs │ ├── LambdajectionVersionAttribute.cs │ ├── NotValidatedAttribute.cs │ ├── RequiresIamPermissionAttribute.cs │ ├── build │ │ └── Lambdajection.Framework.props │ └── packages.lock.json ├── Generator │ ├── Analyzers │ │ ├── IamAccessAnalyzer.cs │ │ └── InterfaceImplementationAnalyzer.cs │ ├── Attributes │ │ └── AttributeFactory.cs │ ├── AwsFactoryGenerator.cs │ ├── AwsServiceMetadata.cs │ ├── ConfiguratorGenerator.cs │ ├── Generator.csproj │ ├── GeneratorHost.cs │ ├── Internal │ │ └── IsExternalInit.cs │ ├── LambdaCompilationScanResult.cs │ ├── LambdaCompilationScanner.cs │ ├── LambdaGenerator.cs │ ├── OptionClass.cs │ ├── OptionsDecryptorGenerator.cs │ ├── Program.cs │ ├── ProgramContext.cs │ ├── ProgramHost.cs │ ├── Startup.cs │ ├── TemplateGeneration │ │ ├── Converters │ │ │ ├── GetAttTagConverter.cs │ │ │ └── SubTagConverter.cs │ │ ├── Models │ │ │ ├── Export.cs │ │ │ ├── GetAttTag.cs │ │ │ ├── LambdaInfo.cs │ │ │ ├── Output.cs │ │ │ ├── Policy.cs │ │ │ ├── PolicyDocument.cs │ │ │ ├── PolicyStatement.cs │ │ │ ├── Principal.cs │ │ │ ├── Resource.cs │ │ │ ├── Role.cs │ │ │ └── SubTag.cs │ │ └── TemplateGenerator.cs │ ├── TypeExtensions.cs │ ├── UnitGenerator.cs │ ├── UsingsGenerator.cs │ ├── ValidationsGenerator.cs │ ├── build │ │ └── Lambdajection.Generator.props │ └── packages.lock.json ├── Layer │ ├── Layer.csproj │ ├── Layer.template.yml │ ├── Manifest │ │ └── Manifest.csproj │ ├── THIRD-PARTY-NOTICES.txt │ ├── build │ │ └── Lambdajection.Layer.props │ └── packages.lock.json ├── Metapackage │ ├── Metapackage.csproj │ ├── build │ │ ├── Lambdajection.props │ │ └── Lambdajection.targets │ └── packages.lock.json ├── Runtime │ ├── Runtime.csproj │ ├── build │ │ └── Lambdajection.Runtime.props │ └── packages.lock.json ├── Sns │ ├── ISnsEventHandler.cs │ ├── Models │ │ ├── CloudFormationStackEvent.cs │ │ ├── SnsEvent.cs │ │ ├── SnsMessage.cs │ │ ├── SnsMessageAttribute.cs │ │ └── SnsRecord.cs │ ├── Serialization │ │ └── CloudFormationStackEventConverter.cs │ ├── Sns.csproj │ ├── SnsLambdaHost.cs │ └── packages.lock.json ├── Templates │ ├── Templates.csproj │ └── packages.lock.json └── Tracing │ ├── Tracing.csproj │ ├── build │ └── Lambdajection.Tracing.props │ └── packages.lock.json ├── stylecop.json ├── templates ├── Directory.Build.props ├── Options │ ├── .excludecsproj │ ├── .template.config │ │ └── template.json │ ├── Options.cs │ └── Options.csproj ├── Project │ ├── .template.config │ │ └── template.json │ ├── Handler.cs │ ├── Project.csproj │ └── Startup.cs └── templates.sln ├── tests ├── Common │ ├── AsyncDisposableLambda.cs │ ├── AutoAttribute.cs │ ├── DisposableLambda.cs │ ├── MultiDisposableLambda.cs │ ├── TargetAttribute.cs │ ├── TargetRelay.cs │ ├── TestConfigFactory.cs │ ├── TestConfigurator.cs │ ├── TestCustomResourceLambda.cs │ ├── TestCustomResourceOutputData.cs │ ├── TestLambda.cs │ ├── TestLambdaMessage.cs │ ├── TestStartup.cs │ └── TypeOmitter.cs ├── Compilation │ ├── Projects │ │ ├── AmazonFactories │ │ │ ├── AmazonFactories.csproj │ │ │ ├── Handler.cs │ │ │ ├── S3Utility.cs │ │ │ └── Startup.cs │ │ ├── ConfigFactory │ │ │ ├── ConfigFactory.csproj │ │ │ ├── Handler.cs │ │ │ ├── JsonConfigFactory.cs │ │ │ ├── Startup.cs │ │ │ └── appsettings.json │ │ ├── Configuration │ │ │ ├── Configuration.csproj │ │ │ ├── Handler.cs │ │ │ ├── Options.cs │ │ │ └── Startup.cs │ │ ├── CustomResources │ │ │ ├── CustomResources.csproj │ │ │ ├── Handler.cs │ │ │ ├── Metadata.cs │ │ │ ├── ResourceProperties.cs │ │ │ ├── ResponseData.cs │ │ │ └── Startup.cs │ │ ├── CustomRunnerMethod │ │ │ ├── CustomRunnerMethod.csproj │ │ │ ├── Handler.cs │ │ │ └── Startup.cs │ │ ├── Directory.Build.props │ │ ├── Disposables │ │ │ ├── AsyncDisposableHandler.cs │ │ │ ├── DisposableHandler.cs │ │ │ ├── Disposables.csproj │ │ │ └── Startup.cs │ │ ├── IamPermissions │ │ │ ├── Handler.cs │ │ │ ├── IamPermissions.csproj │ │ │ ├── Startup.cs │ │ │ └── Utility.cs │ │ ├── LambdaContext │ │ │ ├── Handler.cs │ │ │ ├── LambdaContext.csproj │ │ │ └── Startup.cs │ │ ├── MissingLambdaInterface │ │ │ ├── Handler.cs │ │ │ ├── MissingLambdaInterface.csproj │ │ │ ├── MissingLambdaInterfaceAttribute.cs │ │ │ └── Startup.cs │ │ ├── NoHandleMethod │ │ │ ├── Handler.cs │ │ │ ├── NoHandleMethod.csproj │ │ │ └── Startup.cs │ │ ├── Permissionless │ │ │ ├── Handler.cs │ │ │ ├── Permissionless.csproj │ │ │ └── Startup.cs │ │ ├── Serialization │ │ │ ├── Handler.cs │ │ │ ├── Request.cs │ │ │ ├── Serialization.csproj │ │ │ └── Startup.cs │ │ ├── Sns │ │ │ ├── Handler.cs │ │ │ ├── Sns.csproj │ │ │ └── Startup.cs │ │ ├── Tracing │ │ │ ├── ConcreteAmazonClient.cs │ │ │ ├── ConcreteClientConfig.cs │ │ │ ├── Handler.cs │ │ │ ├── Startup.cs │ │ │ └── Tracing.csproj │ │ └── compilation-projects.sln │ ├── Tests │ │ ├── AmazonFactoriesTests.cs │ │ ├── ConfigFactoryTests.cs │ │ ├── ConfigurationTests.cs │ │ ├── CustomResourcesTests.cs │ │ ├── CustomRunnerMethodTests.cs │ │ ├── DisposablesTests.cs │ │ ├── IamPermissionsTests.cs │ │ ├── LambdaContextTests.cs │ │ ├── MissingLambdaInterfaceTests.cs │ │ ├── NoHandleMethodTests.cs │ │ ├── PermissionlessTests.cs │ │ ├── SerializationTests.cs │ │ ├── Setup.cs │ │ ├── SnsTests.cs │ │ └── TracingTests.cs │ └── Utils │ │ ├── HandlerWrapper.cs │ │ ├── InMemoryServer.cs │ │ ├── IntrinsicNodeDeserializer.cs │ │ ├── IntrinsicNodeTypeResolver.cs │ │ └── MSBuildProjectExtensions.cs ├── Setup.cs ├── TestMetadata.txt ├── Tests.csproj ├── Unit │ ├── Core │ │ ├── DefaultLambdaHostTests.cs │ │ ├── LambdaConfigFactoryTests.cs │ │ ├── LambdaHostBuilderTests.cs │ │ └── Serialization │ │ │ └── JsonSerializerTests.cs │ ├── CustomResource │ │ ├── CustomResourceLambdaHostTests.cs │ │ ├── CustomResourceRequestTypeTests.cs │ │ └── CustomResourceResponseStatusConverterTests.cs │ ├── Encryption │ │ └── DefaultDecryptionServiceTests.cs │ ├── Generator │ │ ├── TypeUtilsTests.cs │ │ └── UsingsGeneratorTests.cs │ └── Sns │ │ ├── Helpers │ │ └── TestSnsLambda.cs │ │ ├── Serialization │ │ └── CloudFormationStackEventConverterTests.cs │ │ └── SnsLambdaHostTests.cs ├── Utils │ ├── CompilationExtensions.cs │ ├── GenerateAssemblyResult.cs │ └── StreamUtils.cs └── packages.lock.json └── version.json /.config/dotnet-tools.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 1, 3 | "isRoot": true, 4 | "tools": { 5 | "nbgv": { 6 | "version": "3.5.119", 7 | "commands": [ 8 | "nbgv" 9 | ] 10 | }, 11 | "dotnet-format": { 12 | "version": "7.0.360304", 13 | "commands": [ 14 | "dotnet-format" 15 | ] 16 | }, 17 | "dotnet-json": { 18 | "version": "1.1.1", 19 | "commands": [ 20 | "dotnet-json" 21 | ] 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: cythral 2 | custom: ["https://paypal.me/cythral"] 3 | -------------------------------------------------------------------------------- /.github/auto_assign.yml: -------------------------------------------------------------------------------- 1 | addReviewers: false 2 | addAssignees: true 3 | numberOfAssignees: 0 4 | assignees: 5 | - talenfisher 6 | -------------------------------------------------------------------------------- /.github/releases/v0.1.7.md: -------------------------------------------------------------------------------- 1 | This release of Lambdajection includes minor changes around package management and build tools: 2 | 3 | - Added SourceLink 4 | - Added Package Descriptions 5 | - Makefile improvements 6 | -------------------------------------------------------------------------------- /.github/releases/v0.1.8.md: -------------------------------------------------------------------------------- 1 | This release introduces no end-user visible changes - it is simply an attempt to fix an issue surrounding the CI/CD system. 2 | -------------------------------------------------------------------------------- /.github/releases/v0.1.9.md: -------------------------------------------------------------------------------- 1 | This release fixes assembly naming to match the PackageId rather than project name, for instance the attributes' project assembly is now named Lambdajection.Attributes rather than just Attributes. 2 | -------------------------------------------------------------------------------- /.github/releases/v0.10.0-beta1.md: -------------------------------------------------------------------------------- 1 | ## Enhancements 2 | 3 | - Uncaught exceptions are now logged as critical errors. 4 | - Exceptions are logged under the "Lambdajection" Log Category, which can be filtered out via ILambdaStartup.ConfigureLogging. 5 | - The Lambdajection Lambda Layer now supports arm64-based lambdas. -------------------------------------------------------------------------------- /.github/releases/v0.10.0-beta2.md: -------------------------------------------------------------------------------- 1 | ## Enhancements 2 | 3 | - Adds an attribute to each Lambdajection assembly called `LambdajectionVersion` which can be used to retrieve the NuGet Package Version of Lambdajection being used. -------------------------------------------------------------------------------- /.github/releases/v0.10.0-beta3.md: -------------------------------------------------------------------------------- 1 | ## Enhancements 2 | 3 | - Enables .NET 7 Support & Drops .NET 6 Support -------------------------------------------------------------------------------- /.github/releases/v0.2.0.md: -------------------------------------------------------------------------------- 1 | This release includes the following: 2 | 3 | * **Package Tags**: Our NuGet packages now contain tags! 4 | * **Default Logger**: A default ILogger is added to the Service Collection that is preconfigured to log to standard output. 5 | * **Cythral.CodeGeneration.Roslyn**: Version bump 0.9.0 - no notable changes, did this to get rid of prerelease warnings during builds. 6 | * **Nerdbank.GitVersioning**: Version bump 3.2.31 - fixes building the project on unsupported linux distributions and versioning differences between local and continuous integration builds. 7 | 8 | 9 | -------------------------------------------------------------------------------- /.github/releases/v0.2.1.md: -------------------------------------------------------------------------------- 1 | This release includes the following: 2 | 3 | - Minor refactor of the LambdaHost class, splitting out static data initialization into a new class, LambdaHostBuilder. 4 | - Introduces the usage of FxCop Analyzers in this project, and a few changes to comply to the ruleset. 5 | - Uses Roslyn Diagnostics to report errors rather than throwing an exception. 6 | -------------------------------------------------------------------------------- /.github/releases/v0.3.0-beta1.md: -------------------------------------------------------------------------------- 1 | This release introduces the following: 2 | 3 | - Add options to your Lambda's IoC container using the new LambdaOptions attribute - no more need for explicitly registering IOptions instances in startup. 4 | - Add AWS Services to your Lambda's IoC container using the IServiceCollection.UseAwsService extension. 5 | - Adding an AWS Service will also automatically add an IAwsFactory to the IoC container for that service. Use it to create clients with an assumed role. 6 | - Factories are only generated if AWSSDK.SecurityToken is a dependency of your project. 7 | -------------------------------------------------------------------------------- /.github/releases/v0.3.0-beta2.md: -------------------------------------------------------------------------------- 1 | This release introduces the following: 2 | 3 | - Lambda.Encryption package 4 | - Use the [Encrypted] attribute on option properties that should be decrypted on startup 5 | - By default, encrypted properties will be decrypted using KMS. 6 | - Use your own decryption service by injecting an IDecryptionService singleton into the IoC container at startup. 7 | - NuGet Package Version Badges in the README! Easily check the latest version of each package right from the Lambdajection repository. 8 | - Documentation comments have been added to public facing APIs. Use Omnisharp/Intellisense to take full advantage of this. 9 | - Examples for adding/using AWS Client Factories and Encrypted Options have been added and linked to in the README. 10 | - **Breaking Change**: Startup classes are now added to the service collection and use constructor DI to inject the IConfiguration object (this matches the approach that ASP NET Core uses). The Configuration property on ILambdaStartup has been removed and is no longer set during lambda startup. 11 | - **Breaking Change**: The LambdaHost constructor allowing a custom builder function/action has been marked as internal, as this was only intended for internal testing purposes. 12 | - Tests are now organized into categories and can be filtered by these categories: Unit and Integration. 13 | - A contributing guide has been added to the repository. 14 | 15 | See the Encrypted Options example for usage of Lambda.Encryption: 16 | https://github.com/cythral/lambdajection/tree/v0.3.0-beta2/examples/EncryptedOptions 17 | -------------------------------------------------------------------------------- /.github/releases/v0.3.0-beta3.md: -------------------------------------------------------------------------------- 1 | This release introduces the following: 2 | 3 | - Fixes an issue where client factories would attempt to do an sts:AssumeRole if no role arn was given. -------------------------------------------------------------------------------- /.github/releases/v0.4.0-beta1.md: -------------------------------------------------------------------------------- 1 | This release introduces the following: 2 | 3 | - You can now control the serializer used on the Lambda by setting the Serializer argument in the Lambda attribute. If your Lambda targets netcoreapp3.1, then DefaultLambdaJsonSerializer from Amazon.Lambda.Serialization.SystemTextJson is used by default. 4 | - The startup argument in the Lambda attribute is now a constructor argument, rather than a named one. This was done to enforce setting the argument earlier in the pipeline, rather than just failing during code generation. 5 | - File-based configuration is now turned off by default in favor of environment variables-based configuration. If you need to add file-based configuration back, you can specify a custom ILambdaConfigFactory type to the Lambda attribute's new ConfigFactory argument. 6 | - Initialize data asynchronously or perform a startup task before the Lambda runs using initialization services! Implement ILambdaInitializationService and add it to the container as a singleton. -------------------------------------------------------------------------------- /.github/releases/v0.4.0-beta2.md: -------------------------------------------------------------------------------- 1 | This release introduces the following: 2 | 3 | - Updates decryption to use initialization services for the following benefits: 4 | - Avoid possibility of deadlocks by not using Task.WaitAll in the post configure hook. 5 | - Run decryption on multiple IOptions in parallel 6 | - Run decryption in parallel with other initialization services. 7 | - Fixes an issue where initialization services were getting called on every call to the Lambda. 8 | - Now checking for correct formatting across the solution after every build, including in CICD. This means PR checks will fail if your changes to not comply with our preferred code style. 9 | - Lambdajection.Attributes has been converted to a reference assembly so that it (and its dependencies) are not copied to the output folder of your project. This package has always only contained symbols that are compile-time only, so this will simply free up space in deployment packages. 10 | - Bumped Amazon.Lambda.Serialization.SystemTextJson to v2.0.2 11 | - Now publishing Symbols + SourceLink information for Lambdajection.Encryption -------------------------------------------------------------------------------- /.github/releases/v0.4.0-beta3.md: -------------------------------------------------------------------------------- 1 | This is a test release using an updated workflow. -------------------------------------------------------------------------------- /.github/releases/v0.4.0.md: -------------------------------------------------------------------------------- 1 | This release introduces the following: 2 | 3 | - Updates several dependencies including: 4 | - AWSSDK (Core, S3, KMS, STS) to latest respective versions for performance, bug, and security updates. 5 | - Microsoft Extensions to 3.1.8 for security updates. 6 | - FxCop Analyzers to 3.3.0 for additional code analyzers 7 | - Various test project dependencies for performance and security updates. 8 | - Addressed suggested changes by new code analyzer rules relating to cancellation tokens and default value assignment. 9 | - Added an example demonstrating how to customize the serializer used for your Lambda. -------------------------------------------------------------------------------- /.github/releases/v0.5.0-beta1.md: -------------------------------------------------------------------------------- 1 | This release introduces the following: 2 | 3 | - .NET Templates are here! Install via `dotnet new -i Lambdajection.Templates`. Templates are available for both projects and options. 4 | - IDisposable and IAsyncDisposable Lambdas are now fully supported. Disposers will be called at the end of each invocation. If you implement both IDisposable and IAsyncDisposable, DisposeAsync will be preferred. 5 | - Added an example for custom config factories. 6 | - Upgrades Roslyn to 3.7.0 (via CodeGeneration.Roslyn) for latest bug and security fixes, along with increased nullability checks. Addressed changes around new possible null references. -------------------------------------------------------------------------------- /.github/releases/v0.5.0-beta2.md: -------------------------------------------------------------------------------- 1 | This release introduces the following: 2 | 3 | - Fixes an issue where several template symbols were being replaced where they should not be (ie Options being replaced in the LambdaOptions attribute if you specified a custom options class name). 4 | - Fixes an issue where an IAwsFactory was not being generated and added to the service collection for IAmazonSecurityTokenService. This was not happening for any other service. 5 | - Initialization services that implement IAsyncDisposabe or IDisposable will now be properly disposed prior to running your Lambda's handler. 6 | - Adds support for Custom Runtimes via the Lambdajection.Runtime package. 7 | - Lambdajection.Generator has been rewritten as a Source Generator and CGR has been ejected from all packages. 8 | - Now building with .NET 5 RC2 SDK -------------------------------------------------------------------------------- /.github/releases/v0.5.0-beta3.md: -------------------------------------------------------------------------------- 1 | This release introduces the following: 2 | 3 | - Fixes an issue where adding a static using statement in a source document would result in a compilation failure. 4 | - Fixes an issue where Lambdajection.Generator was bringing in transitive dependencies to consuming projects. 5 | - Fixes ready to run warnings in the Custom Runtime example. 6 | - Fixes an issue where Cythral.CloudFormation.BuildTasks was bringing in transitive dependencies to example projects. 7 | - Fixes several issues around running tests (multiple restores, organization, test assembly compilation and loading) -------------------------------------------------------------------------------- /.github/releases/v0.5.0.md: -------------------------------------------------------------------------------- 1 | This release introduces the following: 2 | 3 | - Updated outdated dependencies to latest versions, including: 4 | - AWSSDK.Core (3.5.1.20 -> 3.5.1.34) 5 | - AWSSDK.KeyManagementService (3.5.0.22 -> 3.5.0.36) 6 | - Amazon.Lambda.Core (1.1.0 -> 1.2.0) 7 | - Amazon.Lambda.Serialization.SystemTextJson (2.0.2 -> 2.1.0) 8 | - Amazon.Lambda.RuntimeSupport (1.1.1 -> 1.2.0) 9 | - Microsoft.Extensions.* (3.1.8 -> 5.0.0) 10 | - Microsoft.CodeAnalysis.* (3.8.0-4.final -> 3.8.0-5.final) 11 | - Updated testing requirements - now requiring >= 80% Coverage and is being enforced via CI with Codecov. 12 | - Now building using the .NET 5 SDK! 13 | 14 | Also includes everything from the first 3 previews: 15 | 16 | - .NET Core Templates 17 | - Handling disposables and async disposables 18 | - Support for Lambda Custom Runtimes 19 | - Rewritten as a .NET Source Generator 20 | 21 | Release notes for the first 3 previews: 22 | 23 | https://github.com/cythral/lambdajection/releases/tag/v0.5.0-beta1 24 | https://github.com/cythral/lambdajection/releases/tag/v0.5.0-beta2 25 | https://github.com/cythral/lambdajection/releases/tag/v0.5.0-beta3 -------------------------------------------------------------------------------- /.github/releases/v0.6.0-beta1.md: -------------------------------------------------------------------------------- 1 | This release introduces the following: 2 | 3 | - New Project Template Option: disposable - set this to true if you want the generated Lambda to implement IAsyncDisposable and IDisposable. 4 | - Several examples have been updated to illustrate the use of the IAsyncDisposable / IDisposable pattern with Lambdajection. 5 | - As a housekeeping item, CloudFormation stacks for examples are now deleted after end to end tests have finished running. 6 | - The generator has been refactored with better modularity. 7 | - **BREAKING CHANGE**: The context parameter (ILambdaContext) has been removed from ILambda.Handle. This can now (optionally) be accessed via a constructor argument instead. This was done to simplify the composition process and reduce the number of arguments that Handle will have - we plan on introducing cancellation tokens in the future here instead. 8 | - Updated Microsoft.CodeAnalysis.* Dependencies from 3.8.0-5.final to 3.8.0 9 | - Updated AWSSDK.Core from 3.5.1.34 to 3.5.1.42 10 | - Updated AWSSDK.KeyManagementService from 3.5.0.36 to 3.5.0.42 -------------------------------------------------------------------------------- /.github/releases/v0.6.0-beta2.md: -------------------------------------------------------------------------------- 1 | This release introduces the following: 2 | 3 | - You can now shrink package sizes by utilizing the new Lambdajection Layer! For the time being, this is only available for those also using the Lambdajection Custom Runtime. Support for aws-hosted dotnetcore3.1 may be added in a future release. 4 | - The "Run" method name can now be customized using the RunnerMethod property in the Lambda Attribute. -------------------------------------------------------------------------------- /.github/releases/v0.6.0-beta3.md: -------------------------------------------------------------------------------- 1 | This release includes patches to the Lambda Layer, including: 2 | 3 | - Addition of third party notices. 4 | - Inclusion of our License in the Layer. 5 | - Inclusion of our Readme in the Layer. 6 | - Adds the Layer ARN as a CloudFormation template output. 7 | -------------------------------------------------------------------------------- /.github/releases/v0.6.0-beta4.md: -------------------------------------------------------------------------------- 1 | This release introduces the following: 2 | 3 | - **Breaking Change**: Lambdas now take a CancellationToken as a second argument and will gracefully stop execution when cancellation is requested. 4 | - Unit tests have been refactored to use AutoFixture where applicable to conform to best practices regarding generation of test data and setup. -------------------------------------------------------------------------------- /.github/releases/v0.6.0.md: -------------------------------------------------------------------------------- 1 | New in v0.6.0: 2 | 3 | - Upgraded Cythral.CloudFormation.BuildTasks to v0.4.2 for increased end-to-end test stability (these sometimes failed before due to base64 keys containing characters that are not safe for URLs). 4 | - Upgraded AWSSDK.Core to 3.5.1.57 5 | - Upgraded AWSSDK.KeyManagementService to 3.5.1 6 | - Upgraded Microsoft.Extensions.DependencyInjection to 5.0.1 7 | - Upgraded Amazon.Lambda.RuntimeSupport to 1.3.0 8 | 9 | Also includes everything from the first 4 betas: 10 | 11 | - Removed the ILambdaContext parameter. This is now accessible via constructor dependency injection instead. 12 | - Adds a CancellationToken parameter to coordinate cancellation of child tasks. Forward this to any awaited calls in your Handle function. 13 | - The "Run" method name can now be customized. 14 | - A Lambda Layer containing Lambdajection and all its dependencies is now available! See the README for usage. 15 | 16 | ## Prerelease Links 17 | 18 | https://github.com/cythral/lambdajection/releases/tag/v0.6.0-beta1 19 | https://github.com/cythral/lambdajection/releases/tag/v0.6.0-beta2 20 | https://github.com/cythral/lambdajection/releases/tag/v0.6.0-beta3 21 | https://github.com/cythral/lambdajection/releases/tag/v0.6.0-beta4 22 | 23 | ## Whats next? 24 | Please look forward to v0.7.0 in March, which will introduce functionality for Lambdajection-backed Custom Resources! -------------------------------------------------------------------------------- /.github/releases/v0.7.0-beta1.md: -------------------------------------------------------------------------------- 1 | This release introduces the following: 2 | 3 | - Now building with .NET SDK v5.0.102. 4 | - Custom Resources are in preview! See the Custom Resource example for usage details. 5 | -------------------------------------------------------------------------------- /.github/releases/v0.7.0-beta2.md: -------------------------------------------------------------------------------- 1 | Bug Fixes: 2 | 3 | - Fixes an issue where error messages were being suppressed by a different message ('Invalid PhysicalResourceId') after responding to CloudFormation. 4 | 5 | New Features: 6 | 7 | - **Breaking Change**: Data Annotations on all request properties are now validated at runtime for each invocation. A **Validate** method is automatically generated on your Lambda at compile-time to help accomplish this. 8 | 9 | Updates for Contributors: 10 | 11 | - Dependency updates are now automated via Nukeeper 12 | - AWSSDK.Core is no longer a direct dependency of Lambdajection.Generator, but it will still get added to the nuget package so it can be loaded during generation if needed. 13 | - Now Building with .NET 5.0.103 14 | 15 | Runtime Dependency updates: 16 | 17 | - AWSSDK.KeyManagementService to 3.5.2.12 18 | - AWSSDK.Core to 3.5.3.1 19 | - Amazon.Lambda.ApplicationLoadBalancerEvents to 2.1.0 20 | -------------------------------------------------------------------------------- /.github/releases/v0.7.0-beta3.md: -------------------------------------------------------------------------------- 1 | 2 | Bug Fixes: 3 | 4 | - Fixed an issue where the generator would attempt to generate validations for collection types, which would result in a stack overflow. The validations generator no longer recurses into these types, or any type that lives in an assembly that starts with "System" 5 | - Fixed an issue where validations were being generated for private and protected properties. -------------------------------------------------------------------------------- /.github/releases/v0.7.0-beta4.md: -------------------------------------------------------------------------------- 1 | New Features: 2 | 3 | - For Custom Resources, use the UpdateRequiresReplacementAttribute to denote resource properties that, when updated, should create a new resource rather than updating the existing one. CloudFormation will automatically call delete on the old resource when this happens. 4 | 5 | New Packages: 6 | 7 | - Lambdajection.Framework - we moved the framework-specific attributes here (LambdaHostAttribute, LambdaInterfaceAttribute). This will be specifically for attributes that tell the Generator what and how to generate a Lambda. 8 | - Lambdajection.Framework.BuildTime - used by build-time only packages that extend the functionality of the Lambda Generator, such as Lambdajection.CustomResource.BuildTime 9 | - Lambdajection.CustomResource.BuildTime - contains a generator for the RequiresReplacement method on the ICustomResourceProvider interface. 10 | 11 | Enhancements: 12 | 13 | - Lambdajection.Generator no longer includes its own copy of Lambdajection.Core in its NuGet package - we've done some work to dynamically load assemblies in the Generator from outside its package. **You may need to run a clean after upgrading due to these changes.** 14 | - Various 3rd-party dependency upgrades throughout the project. 15 | - Added documentation to the custom resource example. -------------------------------------------------------------------------------- /.github/releases/v0.7.0.md: -------------------------------------------------------------------------------- 1 | ## New Features: 2 | 3 | - Create Lambda-backed Custom Resource Providers using Lambdajection! See the README and example for info. 4 | - Add validation attributes to your request properties, and they will be automatically evaluated. To accomplish this, Lambdajection will generate a method called 'Validate' and add it to your Handler class. 5 | 6 | ## Enhancements: 7 | 8 | - The Generator no longer packages its own version of Lambdajection.Core, instead it will load the one used in the project from your restore directory. **You may need to run a clean after upgrading due to this.** 9 | - Various 3rd party dependency upgrades, including Roslyn to v3.9.0. 10 | - Now building with .NET SDK 5.0.200. 11 | 12 | ## Prerelease Links: 13 | 14 | https://github.com/cythral/lambdajection/releases/tag/v0.7.0-beta1 15 | https://github.com/cythral/lambdajection/releases/tag/v0.7.0-beta2 16 | https://github.com/cythral/lambdajection/releases/tag/v0.7.0-beta3 17 | https://github.com/cythral/lambdajection/releases/tag/v0.7.0-beta4 18 | 19 | ## Whats next? 20 | 21 | Please look forward to v0.8.0 in May, which will introduce CloudFormation template generation and minimum IAM permissions collection. -------------------------------------------------------------------------------- /.github/releases/v0.8.0-beta1.md: -------------------------------------------------------------------------------- 1 | Enhancements: 2 | 3 | - Added cancellationToken parameter to IAwsFactory. 4 | - No longer packaging AWSSDK.Core in the Lambdajection.Generator package - this is restored and resolved from the RestorePackagesPath at build time, along with other generator-specific dependencies. 5 | 6 | Dependency Updates: 7 | 8 | https://github.com/cythral/lambdajection/pulls?q=is%3Apr+is%3Amerged+label%3Anukeeper+milestone%3Av0.8.0+ -------------------------------------------------------------------------------- /.github/releases/v0.8.0-beta2.md: -------------------------------------------------------------------------------- 1 | This release includes a cumulative AWS SDK update to 3.7. -------------------------------------------------------------------------------- /.github/releases/v0.8.0-beta3.md: -------------------------------------------------------------------------------- 1 | This includes a hotfix for v0.8.0-beta2: An earlier version of the AWS SDK was being restored, which did not bring in Microsoft.Bcl.AsyncInterfaces 5.0.0. The restore and assembly load process for the generator has also been simplified further: 2 | 3 | - There is no longer a generator-specific restore, generator dependencies are all restored in the solution-level restore target. 4 | - The generator attempts to load all matching assemblies one at a time, until one loads successfully. Before, it would only attempt to load one. 5 | - Lambdajection.Attributes is no longer a reference assembly. To avoid adding it to the runtime assemblies, we are instead setting PrivateAssets="runtime" wherever it is referenced. With that, Lambdajection.Generator is no longer packaging the attributes assembly. -------------------------------------------------------------------------------- /.github/releases/v0.8.0-beta4.md: -------------------------------------------------------------------------------- 1 | - Adds an IAM Access Analyzer, which will collect the minimum IAM permissions needed for running your lambda or custom resource and output them to a file. By default, this file is located at $(IntermediateOutputPath)IamPermissions.txt, but can be customized via the $(LambdajectionIamPermissionsOutputPath) property. 2 | - Fixed an issue where compilation would sometimes fail for custom resources with an error like 'Could not load file Microsoft.Extensions.Hosting'. -------------------------------------------------------------------------------- /.github/releases/v0.8.0-beta5.md: -------------------------------------------------------------------------------- 1 | - This preview introduces CloudFormation template generation! No extra configuration needed, templates will be generated and output to $(OutDir)/{ClassName}.template.yml 2 | - At the moment, template generation for lambdas using Lambdajection.Runtime and/or Lambdajection.Layer are not supported (this will be added in v0.9.0). 3 | - Templates are generated on a per-lambda basis. An option to combine all lambdas into one template will be provided in future versions. 4 | - IAM permissions are now generated on a per-lambda basis. Permission files go in $(IntermediateOutputPath)/{ClassName}.iam.txt 5 | 6 | -------------------------------------------------------------------------------- /.github/releases/v0.8.1.md: -------------------------------------------------------------------------------- 1 | ## Bug Fixes 2 | 3 | - Fixed an issue where StyleCop and other analyzers were analyzing generated code and causing a bunch of warnings/errors depending on how you have them configured. 4 | - Fixed an issue where projects that had a transitive reference to Lambdajection would produce a warning about how the generator would not contribute any sources, along with not being able to find the "Microsoft.Extensions.Hosting" assembly. -------------------------------------------------------------------------------- /.github/releases/v0.8.2.md: -------------------------------------------------------------------------------- 1 | ## Bug Fixes 2 | 3 | - Fixes an issue where the template generator was using "Handle" instead of "Run" as the method name. -------------------------------------------------------------------------------- /.github/releases/v0.8.3.md: -------------------------------------------------------------------------------- 1 | ## Bug Fixes 2 | 3 | - Fixes an issue where templates generated for Lambdas that don't interact with an AWS API would have a role policy with 0 actions, which is not allowed in CloudFormation. 4 | - Fixes an issue where generation would fail if the project did not have a direct reference to the AWSSDK. 5 | - Fixes an issue where validations were being applied to old resource properties, which would cause resource creation failures if using the validation attributes. 6 | -------------------------------------------------------------------------------- /.github/releases/v0.8.4.md: -------------------------------------------------------------------------------- 1 | ## Bug Fixes 2 | 3 | - Fixes an issue where the Runtime package could not be used in conjunction with the CustomResource package. 4 | - Bumped .NET SDK to 5.0.302 -------------------------------------------------------------------------------- /.github/releases/v0.8.5.md: -------------------------------------------------------------------------------- 1 | - Enables .NET 6 support 2 | - Lambdajection.Layer dual-targets .NET 5 and .NET 6. This unfortunately results in a larger layer size. Future versions will include .NET 6 only. 3 | - Lambdas that include Lambdajection.Runtime will now have to set RuntimeIdentifier and SelfContained properties to true in their csproj due to backwards-incompatible changes in the .NET SDK starting in version 6.0.100. -------------------------------------------------------------------------------- /.github/releases/v0.9.0-beta1.md: -------------------------------------------------------------------------------- 1 | ## Enhancements 2 | 3 | - Request serialization / deserialization is now handled by Lambdajection instead of the serializers provided by Amazon's Runtime Support. This implementation is purely System.Text.Json-based. 4 | - X-Ray Active Tracing can now be easily enabled by adding a PackageReference to the new Lambdajection.Tracing package. -------------------------------------------------------------------------------- /.github/releases/v0.9.0-beta2.md: -------------------------------------------------------------------------------- 1 | - Enables .NET 6 support 2 | - Lambdajection.Layer no longer contains pre-optimized packages due to a bug in the .NET 6 SDK. 3 | - Lambdas that include Lambdajection.Runtime will now have to set RuntimeIdentifier and SelfContained properties to true in their csproj due to backwards-incompatible changes in the .NET SDK starting in version 6.0.100. -------------------------------------------------------------------------------- /.github/releases/v0.9.0-beta3.md: -------------------------------------------------------------------------------- 1 | ## New Features 2 | 3 | - SNS Event Handling is now built in to Lambdajection. Add the Lambdajection.Sns package to your project and use the SnsEventHandlerAttribute to denote Lambdas that are sourced from SNS events. The lambda handler will be invoked once for each SNS record received. 4 | - A model for CloudFormation Stack Notifications is included in the Lambdajection.Sns package for processing stack notification events. -------------------------------------------------------------------------------- /.github/releases/v0.9.0-beta4.md: -------------------------------------------------------------------------------- 1 | # Enhancements 2 | 3 | - CloudFormationStackEvent objects are now serializable. 4 | - ResponseURL is now an optional argument to custom resource requests, to allow for easier testing. 5 | - The lambda output for Custom Resources is now the full response that would've been sent to CloudFormation, rather than just the output data. 6 | 7 | # Bug Fixes 8 | 9 | - Fixes an issue where SnsMessage objects would fail to deserialize. -------------------------------------------------------------------------------- /.github/releases/v0.9.0-beta5.md: -------------------------------------------------------------------------------- 1 | ## Bug Fixes 2 | 3 | - Fixes an issue where deserializing an SnsMessage`CloudFormationStackEvent would result in an error about newlines are not allowed in JSON strings. -------------------------------------------------------------------------------- /.github/releases/v0.9.0.md: -------------------------------------------------------------------------------- 1 | ## Enhancements 2 | 3 | - Request serialization / deserialization is now handled by Lambdajection instead of the serializers provided by Amazon's Runtime Support. This implementation is purely System.Text.Json-based. 4 | - X-Ray Active Tracing can now be easily enabled by adding a PackageReference to the new Lambdajection.Tracing package. 5 | - Enables .NET 6 Support and drops .NET 5 support. 6 | - SNS Event Handling is now built in to Lambdajection. Add the Lambdajection.Sns package to your project and use the SnsEventHandlerAttribute to denote Lambdas that are sourced from SNS events. The lambda handler will be invoked once for each SNS record received. 7 | - A model for CloudFormation Stack Notifications is included in the Lambdajection.Sns package for processing stack notification events. 8 | - The lambda output for Custom Resources is now the full response that would've been sent to CloudFormation, rather than just the output data. -------------------------------------------------------------------------------- /.github/releases/v0.9.1.md: -------------------------------------------------------------------------------- 1 | ## Bug Fixes 2 | 3 | - Fixes an issue where wrong assembly versions may be loaded into the generator's AssemblyLoadContext. -------------------------------------------------------------------------------- /.github/releases/v0.9.2.md: -------------------------------------------------------------------------------- 1 | ## Bug Fixes 2 | 3 | - Fixes an issue where custom resources would sometimes return an 'Invalid PhysicalResourceId' error. -------------------------------------------------------------------------------- /.github/workflows/assign-prs.yml: -------------------------------------------------------------------------------- 1 | name: Assign PR 2 | on: 3 | pull_request_target: 4 | types: [opened, reopened, ready_for_review] 5 | 6 | jobs: 7 | add-assignees: 8 | name: Assign 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: kentaro-m/auto-assign-action@v1.2.5 12 | with: 13 | repo-token: ${{ secrets.GH_TOKEN }} 14 | -------------------------------------------------------------------------------- /.github/workflows/codeql-analysis.yml: -------------------------------------------------------------------------------- 1 | name: "CodeQL" 2 | 3 | on: 4 | push: 5 | branches: [master] 6 | schedule: 7 | - cron: "0 0 * * *" 8 | 9 | env: 10 | DOTNET_NOLOGO: "true" 11 | UPLOAD_LAYER_TEMPLATE: "false" 12 | 13 | jobs: 14 | analyze: 15 | name: Analyze 16 | runs-on: ubuntu-latest 17 | 18 | steps: 19 | - name: Checkout repository 20 | uses: actions/checkout@v3 21 | with: 22 | fetch-depth: 0 23 | 24 | - name: Setup .NET Core 25 | uses: actions/setup-dotnet@v3 26 | 27 | - name: Initialize CodeQL 28 | uses: github/codeql-action/init@v2 29 | 30 | - name: Build 31 | run: dotnet build 32 | 33 | - name: Perform CodeQL Analysis 34 | uses: github/codeql-action/analyze@v2 35 | 36 | - name: Discord Failure Notification 37 | uses: Ilshidur/action-discord@master 38 | if: failure() && (github.event_name == 'push' || github.event_name == 'schedule') 39 | env: 40 | DISCORD_WEBHOOK: ${{ secrets.DISCORD_WEBHOOK }} 41 | DISCORD_EMBEDS: | 42 | [ 43 | { 44 | "title": "[${{ github.repository }}] CodeQL Failed", 45 | "url": "https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}", 46 | "description": "An error occurred while analyzing ${{ github.repository }}", 47 | "color": 12720135 48 | } 49 | ] 50 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .vs/ 2 | bin/ 3 | obj/ 4 | .nuget/ 5 | .ionide/ 6 | .fake 7 | .env 8 | -------------------------------------------------------------------------------- /.vscode/csharp.code-snippets: -------------------------------------------------------------------------------- 1 | { 2 | "Test Suite": { 3 | "prefix": "testsuite", 4 | "body": [ 5 | "using System;", 6 | "", 7 | "using NUnit.Framework;", 8 | "", 9 | "namespace Cythral.Brighid.Instructor.Tests", 10 | "{", 11 | " class ${1:SuiteName}", 12 | " {", 13 | " [SetUp]", 14 | " public void SetUp()", 15 | " {", 16 | " }", 17 | " }", 18 | "}" 19 | ] 20 | }, 21 | "Test": { 22 | "prefix": "test", 23 | "body": ["[Test]", "public void ${1:TestName}()", "{", " $0", "}"] 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "ms-dotnettools.csharp", 4 | "editorconfig.editorconfig", 5 | "redhat.vscode-xml", 6 | "tintoy.msbuild-project-tools", 7 | "yzhang.markdown-all-in-one" 8 | ] 9 | } -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to find out which attributes exist for C# debugging 3 | // Use hover for the description of the existing attributes 4 | // For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "name": ".NET Core Launch", 9 | "type": "coreclr", 10 | "request": "launch", 11 | "preLaunchTask": "build", 12 | "program": "${workspaceFolder}/bin/Project.Name/Debug/netcoreapp3.1/Project.Name.dll", 13 | "args": [], 14 | "cwd": "${workspaceFolder}/src", 15 | "stopAtEntry": false, 16 | "serverReadyAction": { 17 | "action": "openExternally", 18 | "pattern": "^\\s*Now listening on:\\s+(https?://\\S+)" 19 | }, 20 | "env": { 21 | "ASPNETCORE_ENVIRONMENT": "Development" 22 | }, 23 | "sourceFileMap": { 24 | "/Views": "${workspaceFolder}/Views" 25 | } 26 | }, 27 | { 28 | "name": ".NET Core Attach", 29 | "type": "coreclr", 30 | "request": "attach", 31 | "processId": "${command:pickProcess}" 32 | }, 33 | { 34 | "name": ".NET Script Debug", 35 | "type": "coreclr", 36 | "request": "launch", 37 | "program": "${env:HOME}/.dotnet/tools/dotnet-script", 38 | "args": ["${file}"], 39 | "windows": { 40 | "program": "${env:USERPROFILE}/.dotnet/tools/dotnet-script.exe" 41 | }, 42 | "cwd": "${workspaceFolder}", 43 | "stopAtEntry": true 44 | } 45 | ] 46 | } 47 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "editor.formatOnSave": true, 3 | "editor.formatOnPaste": true, 4 | "editor.formatOnType": true, 5 | "omnisharp.enableEditorConfigSupport": true, 6 | "omnisharp.enableRoslynAnalyzers": true, 7 | "omnisharp.enableImportCompletion": true, 8 | "prettier.enable": false, 9 | "xml.format.preserveAttributeLineBreaks": true, 10 | "markdown.extension.toc.levels": "2..6", 11 | "editor.semanticHighlighting.enabled": true, 12 | "csharp.semanticHighlighting.enabled": true, 13 | "files.exclude": { 14 | "**/.nuget": true, 15 | }, 16 | "yaml.customTags": [ 17 | "!And", 18 | "!And sequence", 19 | "!If", 20 | "!If sequence", 21 | "!Not", 22 | "!Not sequence", 23 | "!Equals", 24 | "!Equals sequence", 25 | "!Or", 26 | "!Or sequence", 27 | "!FindInMap", 28 | "!FindInMap sequence", 29 | "!Base64", 30 | "!Join", 31 | "!Join sequence", 32 | "!Cidr", 33 | "!Ref", 34 | "!Sub", 35 | "!Sub sequence", 36 | "!GetAtt", 37 | "!GetAZs", 38 | "!ImportValue", 39 | "!ImportValue sequence", 40 | "!Select", 41 | "!Select sequence", 42 | "!Split", 43 | "!Split sequence" 44 | ] 45 | } -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "2.0.0", 3 | "tasks": [ 4 | { 5 | "label": "build", 6 | "command": "dotnet", 7 | "type": "process", 8 | "args": ["build"], 9 | "problemMatcher": "$msCompile" 10 | }, 11 | { 12 | "label": "test", 13 | "command": "dotnet", 14 | "type": "process", 15 | "args": ["test"], 16 | "problemMatcher": "$msCompile" 17 | }, 18 | { 19 | "label": "run unit tests", 20 | "command": "dotnet", 21 | "type": "process", 22 | "args": ["test", "--filter", "Category=Unit"], 23 | "problemMatcher": "$msCompile" 24 | }, 25 | { 26 | "label": "run integration test", 27 | "command": "dotnet", 28 | "type": "process", 29 | "args": ["test", "--filter", "Category=Integration"], 30 | "problemMatcher": "$msCompile" 31 | }, 32 | { 33 | "label": "format", 34 | "command": "dotnet", 35 | "type": "process", 36 | "args": [ 37 | "format", 38 | "${workspaceFolder}/lambdajection.sln", 39 | "--fix-style", 40 | "info" 41 | ], 42 | "problemMatcher": "$msCompile" 43 | }, 44 | { 45 | "label": "format-examples", 46 | "command": "dotnet", 47 | "type": "process", 48 | "args": [ 49 | "format", 50 | "${workspaceFolder}/examples/examples.sln", 51 | "--fix-style", 52 | "info" 53 | ], 54 | "problemMatcher": "$msCompile" 55 | } 56 | ] 57 | } 58 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2021 Cythral LLC 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | .PHONY = clean clean-lockfiles install relock test unit-test integration-test 2 | 3 | clean: 4 | @rm -rf bin obj .nuget examples/.nuget 5 | @dotnet clean 6 | 7 | clean-lockfiles: 8 | @for file in $$(find . -name packages.lock.json); do rm $$file; done 9 | 10 | install: 11 | @dotnet restore 12 | 13 | relock: clean-lockfiles install 14 | 15 | test: 16 | @dotnet test 17 | 18 | unit-test : 19 | @dotnet test --filter Category=Unit 20 | 21 | integration-test: 22 | @dotnet test --filter Category=Integration -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security 2 | 3 | At this time, only the latest minor release (v0.x) will typically receive security patches. Exceptions may be made depending on severity. 4 | 5 | The preferred method of reporting security issues is to open a [JIRA ticket](https://cythral.atlassian.net/jira/software/c/projects/LAMBJ/issues). When creating an issue, please set the issue type to "Security" and enter your email address in the appropriate field. Please **do not** select any issue type other than "Security" for reporting security issues. If you do, the issue will be visible and may put others at risk of exploitation. You should receive one automated reply shortly afterwards, then a follow-up from a maintainer within 24 hours. 6 | 7 | If you are not contacted by a maintainer within 24-hours, please reply to the automated email you were sent, or send an email directly to security@cythral.com and reference the ticket number you were given (LAMBJ-XXXX). Maintainers will contact you via email from one of the following addresses: 8 | 9 | - noreply@automationforjira.com (a reply-to address will be given) 10 | - security@cythral.com 11 | 12 | If for some reason reporting an issue on JIRA does not work, please email security@cythral.com directly with your concern. -------------------------------------------------------------------------------- /codecov.yml: -------------------------------------------------------------------------------- 1 | coverage: 2 | precision: 2 3 | round: down 4 | range: "80...100" 5 | 6 | status: 7 | project: 8 | default: 9 | threshold: 3% 10 | 11 | patch: 12 | default: 13 | target: 50% 14 | threshold: 3% 15 | 16 | ignore: 17 | - "src/Generator" 18 | -------------------------------------------------------------------------------- /examples/AwsClientFactories/.gitignore: -------------------------------------------------------------------------------- 1 | aws-client-factories.template.yml -------------------------------------------------------------------------------- /examples/AwsClientFactories/AwsClientFactories.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net6.0 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 20 | 21 | 22 | 23 | 27 | 28 | -------------------------------------------------------------------------------- /examples/AwsClientFactories/Request.cs: -------------------------------------------------------------------------------- 1 | namespace Lambdajection.Examples.AwsClientFactories 2 | { 3 | public class Request 4 | { 5 | public string RoleArn { get; set; } = ""; 6 | 7 | public string BucketName { get; set; } = ""; 8 | 9 | public string FileName { get; set; } = ""; 10 | 11 | public string Contents { get; set; } = ""; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /examples/AwsClientFactories/Startup.cs: -------------------------------------------------------------------------------- 1 | using Amazon.S3; 2 | 3 | using Lambdajection.Core; 4 | 5 | using Microsoft.Extensions.Configuration; 6 | using Microsoft.Extensions.DependencyInjection; 7 | using Microsoft.Extensions.Logging; 8 | 9 | namespace Lambdajection.Examples.AwsClientFactories 10 | { 11 | public class Startup : ILambdaStartup 12 | { 13 | public IConfiguration Configuration { get; } 14 | 15 | public Startup(IConfiguration configuration) 16 | { 17 | Configuration = configuration; 18 | } 19 | 20 | public void ConfigureServices(IServiceCollection services) 21 | { 22 | services.UseAwsService(); 23 | } 24 | 25 | public void ConfigureLogging(ILoggingBuilder logging) 26 | { 27 | logging.AddFilter("Lambdajection", LogLevel.Information); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /examples/AwsClientFactories/cloudformation.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "Tags": { 3 | "Name": "lambdajection-awsclientfactories", 4 | "Owner": "Cythral", 5 | "OwnerContact": "Talen Fisher", 6 | "Customer": "Cythral", 7 | "CustomerContact": "Talen Fisher" 8 | } 9 | } -------------------------------------------------------------------------------- /examples/CustomConfiguration/Config.cs: -------------------------------------------------------------------------------- 1 | using Lambdajection.Attributes; 2 | 3 | namespace Lambdajection.Examples.CustomConfiguration 4 | { 5 | [LambdaOptions(typeof(Handler), "Config")] 6 | public class Config 7 | { 8 | public string Foo { get; set; } = ""; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /examples/CustomConfiguration/ConfigFactory.cs: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | 3 | using Lambdajection.Core; 4 | 5 | using Microsoft.Extensions.Configuration; 6 | 7 | namespace Lambdajection.Examples.CustomConfiguration 8 | { 9 | public class ConfigFactory : ILambdaConfigFactory 10 | { 11 | public IConfigurationRoot Create() 12 | { 13 | return new ConfigurationBuilder() 14 | .SetBasePath(Directory.GetCurrentDirectory()) 15 | .AddJsonFile("appsettings.json", optional: true) 16 | .Build(); 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /examples/CustomConfiguration/CustomConfiguration.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net6.0 5 | IDE0052 6 | 7 | 8 | 9 | 10 | PreserveNewest 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /examples/CustomConfiguration/Handler.cs: -------------------------------------------------------------------------------- 1 | using System.Threading; 2 | using System.Threading.Tasks; 3 | 4 | using Amazon.Lambda.Core; 5 | 6 | using Lambdajection.Attributes; 7 | 8 | using Microsoft.Extensions.Options; 9 | 10 | namespace Lambdajection.Examples.CustomConfiguration 11 | { 12 | [Lambda(typeof(Startup), ConfigFactory = typeof(ConfigFactory))] 13 | public partial class Handler 14 | { 15 | private readonly Config config; 16 | 17 | public Handler(IOptions config) 18 | { 19 | this.config = config.Value; 20 | } 21 | 22 | public Task Handle(object request, CancellationToken cancellationToken = default) 23 | { 24 | return Task.FromResult(config.Foo); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /examples/CustomConfiguration/Startup.cs: -------------------------------------------------------------------------------- 1 | using Lambdajection.Core; 2 | 3 | using Microsoft.Extensions.Configuration; 4 | using Microsoft.Extensions.DependencyInjection; 5 | using Microsoft.Extensions.Logging; 6 | 7 | namespace Lambdajection.Examples.CustomConfiguration 8 | { 9 | public class Startup : ILambdaStartup 10 | { 11 | private readonly IConfiguration configuration; 12 | 13 | public Startup(IConfiguration configuration) 14 | { 15 | this.configuration = configuration; 16 | } 17 | 18 | public void ConfigureServices(IServiceCollection services) 19 | { 20 | // Inject services into the Lambda's container here 21 | } 22 | 23 | public void ConfigureLogging(ILoggingBuilder logging) 24 | { 25 | logging.AddFilter("Lambdajection", LogLevel.Information); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /examples/CustomConfiguration/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Config": { 3 | "Foo": "Bar" 4 | } 5 | } -------------------------------------------------------------------------------- /examples/CustomConfiguration/cloudformation.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "Tags": { 3 | "Name": "lambdajection-customconfiguration", 4 | "Owner": "Cythral", 5 | "OwnerContact": "Talen Fisher", 6 | "Customer": "Cythral", 7 | "CustomerContact": "Talen Fisher" 8 | } 9 | } -------------------------------------------------------------------------------- /examples/CustomConfiguration/cloudformation.template.yml: -------------------------------------------------------------------------------- 1 | Transform: AWS::Serverless-2016-10-31 2 | Resources: 3 | CustomConfiguration: 4 | Type: AWS::Serverless::Function 5 | Properties: 6 | Handler: CustomConfiguration::Lambdajection.Examples.CustomConfiguration.Handler::Run 7 | Runtime: dotnet6 8 | FunctionName: lambdajection-customconfiguration 9 | Timeout: 300 10 | CodeUri: ../../bin/Examples/CustomConfiguration/Release/net6.0/publish/ 11 | MemorySize: 512 12 | Policies: 13 | - AWSLambdaBasicExecutionRole 14 | 15 | Outputs: 16 | InputPayload: 17 | Value: "{}" 18 | 19 | ExpectedOutput: 20 | Value: '"Bar"' 21 | -------------------------------------------------------------------------------- /examples/CustomResource/CustomResource.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net6.0 5 | ExamineStack 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /examples/CustomResource/Options.cs: -------------------------------------------------------------------------------- 1 | using Lambdajection.Attributes; 2 | 3 | namespace Lambdajection.Examples.CustomResource 4 | { 5 | [LambdaOptions(typeof(PasswordGenerator), "PasswordGen")] 6 | public class Options 7 | { 8 | public uint DefaultLength { get; set; } = 12; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /examples/CustomResource/Request.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | using System.Text.Json.Serialization; 3 | 4 | using Lambdajection.Attributes; 5 | 6 | namespace Lambdajection.Examples.CustomResource 7 | { 8 | public class Request 9 | { 10 | [Range(3, 12)] 11 | [JsonNumberHandling(JsonNumberHandling.AllowReadingFromString)] 12 | [UpdateRequiresReplacement] 13 | public uint? Length { get; set; } = null; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /examples/CustomResource/Response.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | using Lambdajection.CustomResource; 4 | 5 | namespace Lambdajection.Examples.CustomResource 6 | { 7 | public class Response : ICustomResourceOutputData 8 | { 9 | public Response(string password) 10 | { 11 | this.Password = password; 12 | } 13 | 14 | public string Id { get; set; } = Guid.NewGuid().ToString(); 15 | 16 | public string Password { get; set; } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /examples/CustomResource/Startup.cs: -------------------------------------------------------------------------------- 1 | using System.Security.Cryptography; 2 | 3 | using Lambdajection.Core; 4 | 5 | using Microsoft.Extensions.Configuration; 6 | using Microsoft.Extensions.DependencyInjection; 7 | using Microsoft.Extensions.Logging; 8 | 9 | namespace Lambdajection.Examples.CustomResource 10 | { 11 | public class Startup : ILambdaStartup 12 | { 13 | private readonly IConfiguration configuration; 14 | 15 | public Startup(IConfiguration configuration) 16 | { 17 | this.configuration = configuration; 18 | } 19 | 20 | public void ConfigureServices(IServiceCollection services) 21 | { 22 | services.AddSingleton(); 23 | } 24 | 25 | public void ConfigureLogging(ILoggingBuilder logging) 26 | { 27 | logging.AddFilter("Lambdajection", LogLevel.Information); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /examples/CustomResource/cloudformation.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "Tags": { 3 | "Name": "lambdajection-customresource", 4 | "Owner": "Cythral", 5 | "OwnerContact": "Talen Fisher", 6 | "Customer": "Cythral", 7 | "CustomerContact": "Talen Fisher" 8 | } 9 | } -------------------------------------------------------------------------------- /examples/CustomResource/cloudformation.template.yml: -------------------------------------------------------------------------------- 1 | Transform: AWS::Serverless-2016-10-31 2 | Resources: 3 | CustomResource: 4 | Type: AWS::Serverless::Function 5 | Properties: 6 | Handler: CustomResource::Lambdajection.Examples.CustomResource.PasswordGenerator::Run 7 | Runtime: dotnet6 8 | FunctionName: lambdajection-customresource 9 | Timeout: 300 10 | CodeUri: ../../bin/Examples/CustomResource/Release/net6.0/publish/ 11 | MemorySize: 512 12 | Policies: 13 | - AWSLambdaBasicExecutionRole 14 | Environment: 15 | Variables: 16 | PasswordGen__DefaultLength: "26" 17 | 18 | GeneratedPassword: 19 | Type: Custom::Password 20 | Properties: 21 | ServiceToken: !GetAtt CustomResource.Arn 22 | Length: 5 23 | 24 | Outputs: 25 | InputPayload: 26 | Value: "{}" 27 | 28 | ExpectedOutput: 29 | Value: !Sub '"${GeneratedPassword.Password}"' 30 | -------------------------------------------------------------------------------- /examples/CustomRuntime/CustomRuntime.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net7.0 6 | linux-x64 7 | true 8 | true 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /examples/CustomRuntime/Handler.cs: -------------------------------------------------------------------------------- 1 | using System.Threading; 2 | using System.Threading.Tasks; 3 | 4 | using Amazon.Lambda.Core; 5 | 6 | using Lambdajection.Attributes; 7 | 8 | namespace Lambdajection.Examples.CustomRuntime 9 | { 10 | [Lambda(typeof(Startup))] 11 | public partial class Handler 12 | { 13 | public async Task Handle(object request, CancellationToken cancellationToken = default) 14 | { 15 | return await Task.FromResult("Hello World!"); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /examples/CustomRuntime/Startup.cs: -------------------------------------------------------------------------------- 1 | using Lambdajection.Core; 2 | 3 | using Microsoft.Extensions.DependencyInjection; 4 | using Microsoft.Extensions.Logging; 5 | 6 | namespace Lambdajection.Examples.CustomRuntime 7 | { 8 | public class Startup : ILambdaStartup 9 | { 10 | public void ConfigureServices(IServiceCollection services) 11 | { 12 | // Inject services into the Lambda's container here 13 | } 14 | 15 | public void ConfigureLogging(ILoggingBuilder logging) 16 | { 17 | logging.AddFilter("Lambdajection", LogLevel.Information); 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /examples/CustomRuntime/cloudformation.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "Parameters": { 3 | "DotnetVersion": "7.0.202" 4 | }, 5 | "Tags": { 6 | "Name": "lambdajection-customruntime", 7 | "Owner": "Cythral", 8 | "OwnerContact": "Talen Fisher", 9 | "Customer": "Cythral", 10 | "CustomerContact": "Talen Fisher" 11 | } 12 | } -------------------------------------------------------------------------------- /examples/CustomRuntime/cloudformation.template.yml: -------------------------------------------------------------------------------- 1 | Transform: AWS::Serverless-2016-10-31 2 | Parameters: 3 | DotnetVersion: 4 | Type: String 5 | Description: Version of .NET to use. 6 | 7 | Resources: 8 | LambdajectionLayer: 9 | Type: AWS::CloudFormation::Stack 10 | Properties: 11 | # Requires that dotnet build be run with UPLOAD_LAYER_TEMPLATE=true and OutputLayerTemplateFilePath=./Layer.template.yml 12 | TemplateURL: ../../Layer.template.yml 13 | 14 | CustomRuntime: 15 | Type: AWS::Serverless::Function 16 | Properties: 17 | Handler: CustomRuntime::Lambdajection.Examples.CustomRuntime.Handler::Run 18 | Runtime: provided.al2 19 | FunctionName: lambdajection-customruntime 20 | Timeout: 300 21 | CodeUri: ../../bin/Examples/CustomRuntime/Release/net7.0/linux-x64/publish/ 22 | MemorySize: 512 23 | Layers: 24 | # https://github.com/cythral/dotnet-lambda-layer 25 | - !Sub "{{resolve:ssm:/dotnet/${DotnetVersion}/layer-arn}}" 26 | - !GetAtt LambdajectionLayer.Outputs.LayerArn 27 | Policies: 28 | - AWSLambdaBasicExecutionRole 29 | 30 | Outputs: 31 | InputPayload: 32 | Value: "{}" 33 | 34 | ExpectedOutput: 35 | Value: '"Hello World!"' 36 | -------------------------------------------------------------------------------- /examples/EncryptedOptions/.gitignore: -------------------------------------------------------------------------------- 1 | encrypted-options.template.yml -------------------------------------------------------------------------------- /examples/EncryptedOptions/EncryptedOptions.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | net6.0 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /examples/EncryptedOptions/Handler.cs: -------------------------------------------------------------------------------- 1 | using System.Threading; 2 | using System.Threading.Tasks; 3 | 4 | using Amazon.Lambda.Core; 5 | 6 | using Lambdajection.Attributes; 7 | 8 | using Microsoft.Extensions.Options; 9 | 10 | namespace Lambdajection.Examples.EncryptedOptions 11 | { 12 | [Lambda(typeof(Startup))] 13 | public partial class Handler 14 | { 15 | private readonly Options options; 16 | 17 | public Handler(IOptions options) 18 | { 19 | this.options = options.Value; 20 | } 21 | 22 | public Task Handle(object request, CancellationToken cancellationToken = default) 23 | { 24 | return Task.FromResult(options.EncryptedValue); // despite the name, this value will have already been decrypted for you. 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /examples/EncryptedOptions/Options.cs: -------------------------------------------------------------------------------- 1 | using Lambdajection.Attributes; 2 | using Lambdajection.Encryption; 3 | 4 | namespace Lambdajection.Examples.EncryptedOptions 5 | { 6 | [LambdaOptions(typeof(Handler), "Lambda")] 7 | public class Options 8 | { 9 | [Encrypted] 10 | public string EncryptedValue { get; set; } = ""; 11 | 12 | /// expected plaintext version of the encrypted value 13 | public string ExpectedValue { get; set; } = ""; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /examples/EncryptedOptions/Startup.cs: -------------------------------------------------------------------------------- 1 | using Lambdajection.Core; 2 | 3 | using Microsoft.Extensions.Configuration; 4 | using Microsoft.Extensions.DependencyInjection; 5 | using Microsoft.Extensions.Logging; 6 | 7 | namespace Lambdajection.Examples.EncryptedOptions 8 | { 9 | public class Startup : ILambdaStartup 10 | { 11 | public IConfiguration Configuration { get; } 12 | 13 | public Startup(IConfiguration configuration) 14 | { 15 | Configuration = configuration; 16 | } 17 | 18 | public void ConfigureServices(IServiceCollection services) 19 | { 20 | // You can add your own decryption service here. The default decryption service uses KMS to decrypt values. 21 | // During testing, you can replace this value with a substitute: 22 | 23 | // var decryptionService = Substitute.For(); 24 | // services.AddSingleton(decryptionService); 25 | } 26 | 27 | public void ConfigureLogging(ILoggingBuilder logging) 28 | { 29 | logging.AddFilter("Lambdajection", LogLevel.Information); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /examples/EncryptedOptions/cloudformation.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "Parameters": { 3 | "EncryptedValue": "AQICAHhIUP9wSo8526GK0EpgereFuvGyNnQqxZ6QyX0eg47x7gGIRymCOlsszKlmoEwdxhxYAAAAdTBzBgkqhkiG9w0BBwagZjBkAgEAMF8GCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQMLyTV3PqW7spKORzPAgEQgDIce2Gxv2mRHEk58kZ/Jg5PnEHa9U5/VVb2snVrwbTnHBYnsD1oehv+uzO2+WKcDj8jrg==" 4 | }, 5 | "Tags": { 6 | "Name": "lambdajection-encryptedoptions", 7 | "Owner": "Cythral", 8 | "OwnerContact": "Talen Fisher", 9 | "Customer": "Cythral", 10 | "CustomerContact": "Talen Fisher" 11 | } 12 | } -------------------------------------------------------------------------------- /examples/EncryptedOptions/cloudformation.template.yml: -------------------------------------------------------------------------------- 1 | Transform: AWS::Serverless-2016-10-31 2 | Parameters: 3 | EncryptedValue: 4 | Type: String 5 | Description: A value for the encrypted options lambda to decrypt 6 | 7 | Resources: 8 | EncryptedOptions: 9 | Type: AWS::Serverless::Function 10 | Properties: 11 | Handler: EncryptedOptions::Lambdajection.Examples.EncryptedOptions.Handler::Run 12 | Runtime: dotnet6 13 | FunctionName: lambdajection-encryptedoptions 14 | Timeout: 300 15 | CodeUri: ../../bin/Examples/EncryptedOptions/Release/net6.0/publish/ 16 | MemorySize: 512 17 | Policies: 18 | - AWSLambdaBasicExecutionRole 19 | # Replace this with the ARN of a policy containing the kms:Decrypt permission 20 | - !ImportValue lambdajection-infrastructure:EncryptionKeyDecryptPolicyArn 21 | Environment: 22 | Variables: 23 | # Replace the value here with a KMS-encrypted string 24 | Lambda__EncryptedValue: !Ref EncryptedValue 25 | 26 | Outputs: 27 | InputPayload: 28 | Value: "{}" 29 | 30 | ExpectedOutput: 31 | Value: '"Example Encrypted Value"' 32 | -------------------------------------------------------------------------------- /examples/SnsHandler/Response.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | using Lambdajection.CustomResource; 4 | 5 | namespace Lambdajection.Examples.SnsHandler 6 | { 7 | public class Response : ICustomResourceOutputData 8 | { 9 | public string Id { get; set; } = Guid.NewGuid().ToString(); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /examples/SnsHandler/SnsHandler.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | net6.0 4 | ExamineStack 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /examples/SnsHandler/Startup.cs: -------------------------------------------------------------------------------- 1 | using Lambdajection.Core; 2 | 3 | using Microsoft.Extensions.Configuration; 4 | using Microsoft.Extensions.DependencyInjection; 5 | using Microsoft.Extensions.Logging; 6 | 7 | namespace Lambdajection.Examples.SnsHandler 8 | { 9 | public class Startup : ILambdaStartup 10 | { 11 | public IConfiguration Configuration { get; } 12 | 13 | public Startup(IConfiguration configuration) 14 | { 15 | Configuration = configuration; 16 | } 17 | 18 | public void ConfigureServices(IServiceCollection services) 19 | { 20 | services.AddSingleton(); 21 | } 22 | 23 | public void ConfigureLogging(ILoggingBuilder logging) 24 | { 25 | logging.AddFilter("Lambdajection", LogLevel.Information); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /examples/SnsHandler/cloudformation.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "Tags": { 3 | "Name": "lambdajection-snshandler", 4 | "Owner": "Cythral", 5 | "OwnerContact": "Talen Fisher", 6 | "Customer": "Cythral", 7 | "CustomerContact": "Talen Fisher" 8 | } 9 | } -------------------------------------------------------------------------------- /examples/SnsHandler/cloudformation.template.yml: -------------------------------------------------------------------------------- 1 | Transform: AWS::Serverless-2016-10-31 2 | Resources: 3 | SnsHandler: 4 | Type: AWS::Serverless::Function 5 | Properties: 6 | Handler: SnsHandler::Lambdajection.Examples.SnsHandler.Handler::Run 7 | Runtime: dotnet6 8 | FunctionName: lambdajection-snshandler 9 | Timeout: 300 10 | CodeUri: ../../bin/Examples/SnsHandler/Release/net6.0/publish/ 11 | MemorySize: 512 12 | Policies: 13 | - AWSLambdaBasicExecutionRole 14 | Events: 15 | Sns: 16 | Type: SNS 17 | Properties: 18 | Topic: !Ref Topic 19 | 20 | Topic: 21 | Type: AWS::SNS::Topic 22 | 23 | TopicInvocation: 24 | Type: Custom::Invocation 25 | DeletionPolicy: Retain 26 | DependsOn: 27 | - SnsHandler 28 | - SnsHandlerSns 29 | - SnsHandlerSnsPermission 30 | Properties: 31 | ServiceToken: !Ref Topic 32 | 33 | Outputs: 34 | InputPayload: 35 | Value: "{}" 36 | 37 | ExpectedOutput: 38 | Value: !Sub '"${TopicInvocation.Id}"' 39 | -------------------------------------------------------------------------------- /global.json: -------------------------------------------------------------------------------- 1 | { 2 | "sdk": { 3 | "version": "7.0.202" 4 | } 5 | } -------------------------------------------------------------------------------- /nuget.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /omnisharp.json: -------------------------------------------------------------------------------- 1 | { 2 | "FormattingOptions": { 3 | "OrganizeImports": true 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://docs.renovatebot.com/renovate-schema.json", 3 | "extends": [ 4 | "local>cythral/.github:renovate-config" 5 | ] 6 | } 7 | -------------------------------------------------------------------------------- /src/Attributes/Attributes.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netstandard2.1 5 | Lambdajection.Attributes 6 | NU5128;NU5131 7 | $(PackageId) 8 | true 9 | Includes attributes needed for writing AWS Lambdas using Dependency Injection. 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /src/Attributes/CustomResourceProviderAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | 4 | using Lambdajection.Framework; 5 | 6 | namespace Lambdajection.Attributes 7 | { 8 | /// 9 | /// Class attribute for Custom Resource Providers. Adding this attribute to a class generates a Run method and LambdaConfigurator 10 | /// subclass. This attribute cannot be accessed using reflection - it is only present at build time. 11 | /// 12 | [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)] 13 | [Conditional("CodeGeneration")] 14 | [LambdaHost("Lambdajection.CustomResource", "CustomResourceLambdaHost")] 15 | [LambdaInterface("Lambdajection.CustomResource", "ICustomResourceProvider")] 16 | public class CustomResourceProviderAttribute : LambdaAttribute 17 | { 18 | /// 19 | /// Initializes a new instance of the class. 20 | /// 21 | /// The type of startup class to use for the custom resource provider. 22 | public CustomResourceProviderAttribute(Type startup) 23 | : base(startup) 24 | { 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/Attributes/LambdaOptionsAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | 4 | namespace Lambdajection.Attributes 5 | { 6 | /// 7 | /// Attribute to add options to a Lambda. Adds an IOptions for the targeted class to the specified Lambda. The option values 8 | /// are taken from the configuration section specified by the SectionName argument. 9 | /// 10 | [AttributeUsage(AttributeTargets.Class, AllowMultiple = false)] 11 | [Conditional("CodeGeneration")] 12 | public class LambdaOptionsAttribute : Attribute 13 | { 14 | /// 15 | /// Initializes a new instance of the class. 16 | /// 17 | /// The lambda type to add options to. 18 | /// The section name to read option values from. 19 | public LambdaOptionsAttribute(Type lambdaType, string sectionName) 20 | { 21 | LambdaType = lambdaType; 22 | SectionName = sectionName; 23 | } 24 | 25 | /// Gets or sets the lambda handler type to add options to. 26 | /// The lambda type to add options to. 27 | public Type LambdaType { get; set; } 28 | 29 | /// Gets or sets the options section name. 30 | /// The section name to read option values from. 31 | public string SectionName { get; set; } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/Attributes/SnsEventHandlerAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | 4 | using Lambdajection.Framework; 5 | 6 | namespace Lambdajection.Attributes 7 | { 8 | /// 9 | /// Class attribute for SNS Event Handlers. Adding this attribute to a class generates a Run method and LambdaConfigurator 10 | /// subclass. This attribute cannot be accessed using reflection - it is only present at build time. 11 | /// 12 | [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)] 13 | [Conditional("CodeGeneration")] 14 | [LambdaHost("Lambdajection.Sns", "SnsLambdaHost")] 15 | [LambdaInterface("Lambdajection.Sns", "ISnsEventHandler")] 16 | public class SnsEventHandlerAttribute : LambdaAttribute 17 | { 18 | /// 19 | /// Initializes a new instance of the class. 20 | /// 21 | /// The type of startup class to use for the custom resource provider. 22 | public SnsEventHandlerAttribute(Type startup) 23 | : base(startup) 24 | { 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/Attributes/UpdateRequiresReplacementAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | 4 | namespace Lambdajection.Attributes 5 | { 6 | /// 7 | /// Attribute used to denote properties that, when changed, cause a custom resource to be replaced. 8 | /// 9 | [AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] 10 | [Conditional("CodeGeneration")] 11 | public class UpdateRequiresReplacementAttribute : Attribute 12 | { 13 | /// 14 | /// Initializes a new instance of the class. 15 | /// 16 | public UpdateRequiresReplacementAttribute() 17 | { 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/Core/Exceptions/InvalidLambdaParameterException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Lambdajection.Core.Exceptions 4 | { 5 | /// 6 | /// Exception thrown when there is a problem with the lambda request parameter. 7 | /// 8 | public class InvalidLambdaParameterException : Exception 9 | { 10 | /// 11 | /// Initializes a new instance of the class. 12 | /// 13 | public InvalidLambdaParameterException() 14 | : base("The given lambda parameter was invalid and could not be read from the input stream.") 15 | { 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/Core/IAwsFactory.cs: -------------------------------------------------------------------------------- 1 | using System.Threading; 2 | using System.Threading.Tasks; 3 | 4 | using Amazon.Runtime; 5 | 6 | namespace Lambdajection.Core 7 | { 8 | /// 9 | /// Describes an Amazon Service Client factory which creates clients whose credentials can be the result 10 | /// of assuming a role. 11 | /// 12 | /// The interface type of the Amazon Service Client to create. 13 | public interface IAwsFactory 14 | where TAmazonService : IAmazonService 15 | { 16 | /// 17 | /// Creates an Amazon Service Client of type TAmazonService. 18 | /// 19 | /// ARN of the role to assume for obtaining security credentials. 20 | /// Token used to cancel the task. 21 | /// An Amazon Service Client with credentials that were the result of assuming the given role arn. 22 | Task Create(string? roleArn = null, CancellationToken cancellationToken = default); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/Core/IHttpClient.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading; 3 | using System.Threading.Tasks; 4 | 5 | namespace Lambdajection.Core 6 | { 7 | /// 8 | /// An HTTP Client. 9 | /// 10 | public interface IHttpClient 11 | { 12 | /// 13 | /// Sends a PUT request with the specified payload and content type. 14 | /// 15 | /// The URI to send a request to. 16 | /// The JSON body to send in the request. 17 | /// The content type to use in the request. 18 | /// Token used to cancel the operation. 19 | /// The type of payload. 20 | /// Nothing. 21 | Task PutJson(Uri requestUri, TPayload payload, string? contentType = "application/json", CancellationToken cancellationToken = default); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/Core/ILambda.cs: -------------------------------------------------------------------------------- 1 | using System.Threading; 2 | using System.Threading.Tasks; 3 | 4 | using Lambdajection.Framework; 5 | 6 | namespace Lambdajection.Core 7 | { 8 | /// 9 | /// Describes an Amazon Lambda function. 10 | /// 11 | /// The type of the lambda's input parameter. 12 | /// The type of the lambda's return value. 13 | public interface ILambda 14 | { 15 | /// 16 | /// The lambda's entrypoint. 17 | /// 18 | /// The lambda's input parameter. 19 | /// Token used to cancel the operation. 20 | /// The lambda's return value. 21 | Task Handle(TLambdaParameter parameter, CancellationToken cancellationToken = default); 22 | 23 | /// 24 | /// Runs validations the lambda's input parameter. 25 | /// 26 | /// The lambda's input parameter. 27 | [Generated("Lambdajection.Generator", "Lambdajection.Generator.ValidationsGenerator")] 28 | void Validate(TLambdaParameter parameter); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/Core/ILambdaConfigFactory.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.Configuration; 2 | 3 | namespace Lambdajection.Core 4 | { 5 | /// 6 | /// Describes a configuration factory for a Lambda. 7 | /// 8 | public interface ILambdaConfigFactory 9 | { 10 | /// 11 | /// Creates a configuration object. 12 | /// 13 | /// The resulting configuration object. 14 | IConfigurationRoot Create(); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/Core/ILambdaConfigurator.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.Configuration; 2 | using Microsoft.Extensions.DependencyInjection; 3 | 4 | namespace Lambdajection.Core 5 | { 6 | /// 7 | /// Describes a lambda configurator. A lambda configurator sets up the options to use and any Amazon Service Clients. 8 | /// 9 | public interface ILambdaConfigurator 10 | { 11 | /// 12 | /// Configures options to use for the lambda. 13 | /// 14 | /// The configuration for the lambda. 15 | /// Collection of services used by the lambda's container. 16 | void ConfigureOptions(IConfiguration configuration, IServiceCollection services); 17 | 18 | /// 19 | /// Configures aws services to use for the lambda. 20 | /// 21 | /// Collection of services used by the lambda's container. 22 | void ConfigureAwsServices(IServiceCollection services); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/Core/ILambdaInitializationService.cs: -------------------------------------------------------------------------------- 1 | using System.Threading; 2 | using System.Threading.Tasks; 3 | 4 | namespace Lambdajection.Core 5 | { 6 | /// 7 | /// Describes a lambda initialization service, which gets run immediately before the lambda is. 8 | /// 9 | public interface ILambdaInitializationService 10 | { 11 | /// 12 | /// Runs the initialization service's instructions. 13 | /// 14 | /// Token used to cancel operation. 15 | /// The initialization task. 16 | Task Initialize(CancellationToken cancellationToken = default); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/Core/ILambdaStartup.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.DependencyInjection; 2 | using Microsoft.Extensions.Logging; 3 | 4 | namespace Lambdajection.Core 5 | { 6 | /// 7 | /// Describes a startup class for a lambda which configures services and logging used 8 | /// in the lambda's IoC container. 9 | /// 10 | public interface ILambdaStartup 11 | { 12 | /// 13 | /// Configures services to be injected into the lambda's IoC container. 14 | /// 15 | /// Collection of services that are injected into the lambda's IoC container. 16 | void ConfigureServices(IServiceCollection services); 17 | 18 | /// 19 | /// Configures the logging to be used in the lambda's IoC container. 20 | /// 21 | /// Object used to build a lambda logger. 22 | void ConfigureLogging(ILoggingBuilder logging) 23 | { 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/Core/LambdaConfigFactory.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.Configuration; 2 | 3 | namespace Lambdajection.Core 4 | { 5 | /// 6 | /// The default lambda config factory. 7 | /// 8 | public class LambdaConfigFactory : ILambdaConfigFactory 9 | { 10 | /// 11 | /// Creates the default configuration object. 12 | /// 13 | /// The default configuration object. 14 | public IConfigurationRoot Create() 15 | { 16 | return new ConfigurationBuilder() 17 | .AddEnvironmentVariables() 18 | .Build(); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/Core/LambdaScope.cs: -------------------------------------------------------------------------------- 1 | using Amazon.Lambda.Core; 2 | 3 | #pragma warning disable SA1600, CS1591 4 | 5 | namespace Lambdajection.Core 6 | { 7 | /// 8 | /// Container for lambda invocation-specific variables. 9 | /// 10 | public class LambdaScope 11 | { 12 | /// 13 | /// Gets or sets the lambda context. 14 | /// 15 | /// The lambda context. 16 | public virtual ILambdaContext? LambdaContext { get; set; } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/Core/LambdaServiceCollectionExtensions.cs: -------------------------------------------------------------------------------- 1 | using Amazon.Runtime; 2 | 3 | using Microsoft.Extensions.DependencyInjection; 4 | 5 | namespace Lambdajection.Core 6 | { 7 | /// 8 | /// IServiceCollection extensions for Lambdajection. 9 | /// 10 | public static class LambdaServiceCollectionExtensions 11 | { 12 | #pragma warning disable IDE0060 13 | 14 | /// 15 | /// Adds an Aws Service to the IoC container. If AWSSDK.SecurityToken is a dependency of your project, then an 16 | /// is also added to your lambda's container. 17 | /// 18 | /// Services to be injected into the lambda's container. 19 | /// The interface type of the Amazon Service Client to use. 20 | public static void UseAwsService(this IServiceCollection serviceCollection) 21 | where TAwsService : IAmazonService 22 | { 23 | // logic handled by generator 24 | } 25 | 26 | #pragma warning restore IDE0060 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/Core/Serialization/JsonSerializerSettings.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json; 2 | 3 | namespace Lambdajection.Core.Serialization 4 | { 5 | /// 6 | /// Wrapper around JsonSerializerOptions to allow a default set of options to be used 7 | /// in case the user does not specify one. 8 | /// 9 | public class JsonSerializerSettings 10 | { 11 | /// 12 | /// Initializes a new instance of the class. 13 | /// 14 | /// The json serializer options to use. 15 | public JsonSerializerSettings(JsonSerializerOptions options) 16 | { 17 | Options = options; 18 | } 19 | 20 | /// 21 | /// Gets the json serializer options. 22 | /// 23 | public JsonSerializerOptions Options { get; } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/Core/Serialization/StringConverterFactory.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text.Json; 3 | using System.Text.Json.Serialization; 4 | 5 | namespace Lambdajection.Core.Serialization 6 | { 7 | /// 8 | /// Converts a JSON string to a type. 9 | /// 10 | public class StringConverterFactory : JsonConverterFactory 11 | { 12 | /// 13 | public override bool CanConvert(Type typeToConvert) 14 | { 15 | return true; 16 | } 17 | 18 | /// 19 | public override JsonConverter? CreateConverter(Type typeToConvert, JsonSerializerOptions options) 20 | { 21 | return new StringConverter(typeToConvert); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/Core/build/Lambdajection.Core.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | $(MSBuildThisFileDirectory)..\lib\netstandard2.1\Lambdajection.Core.dll,$(LambdajectionBuildTimeAssemblies) 4 | 5 | -------------------------------------------------------------------------------- /src/CustomResource.BuildTime/build/Lambdajection.CustomResource.BuildTime.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | $(MSBuildThisFileDirectory)..\tools\any\Lambdajection.CustomResource.BuildTime.dll,$(LambdajectionBuildTimeAssemblies) 4 | 5 | -------------------------------------------------------------------------------- /src/CustomResource/CustomResource.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netstandard2.1 5 | Lambdajection.CustomResource 6 | $(PackageId) 7 | true 8 | snupkg 9 | true 10 | Includes interfaces and runtime support classes for writing Lambdajection-backed Custom Resources using Dependency Injection. 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /src/CustomResource/CustomResourceRequestType.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | 3 | namespace Lambdajection.CustomResource 4 | { 5 | /// 6 | /// Describes the type of custom resource request 7 | /// sent by CloudFormation. 8 | /// 9 | [JsonConverter(typeof(JsonStringEnumConverter))] 10 | public enum CustomResourceRequestType 11 | { 12 | /// Request Type used to create a Custom Resource. 13 | Create, 14 | 15 | /// Request Type used to update a Custom Resource. 16 | Update, 17 | 18 | /// RequestType used to delete a Custom Resource. 19 | Delete, 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/CustomResource/CustomResourceRequest{TResourceProperties}.cs: -------------------------------------------------------------------------------- 1 | using Lambdajection.Framework; 2 | 3 | namespace Lambdajection.CustomResource 4 | { 5 | /// 6 | /// Describes a request from CloudFormation to create, 7 | /// update or delete a Custom Resource. 8 | /// 9 | /// 10 | /// The type of resource properties that belong to custom resources provided 11 | /// by this custom resource provider. 12 | /// 13 | public class CustomResourceRequest : CustomResourceRequest 14 | { 15 | /// 16 | /// Gets or sets the resource properties for the requested 17 | /// custom resource. 18 | /// 19 | /// The resource properties for the requested custom resource. 20 | public virtual TResourceProperties? ResourceProperties { get; set; } 21 | 22 | /// 23 | /// Gets or sets the old resource properties for the requested custom resource. 24 | /// This will only be present for update requests. 25 | /// 26 | /// The old resource properties for the requested custom resource. 27 | [NotValidated] 28 | public virtual TResourceProperties? OldResourceProperties { get; set; } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/CustomResource/CustomResourceResponseStatus.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | 3 | namespace Lambdajection.CustomResource 4 | { 5 | /// 6 | /// Describes the status of a response returned 7 | /// from a Custom Resource request. 8 | /// 9 | [JsonConverter(typeof(CustomResourceResponseStatusConverter))] 10 | public enum CustomResourceResponseStatus 11 | { 12 | /// Describes a success response. 13 | Success, 14 | 15 | /// Describes a failure response. 16 | Failed, 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/CustomResource/ICustomResourceOutputData.cs: -------------------------------------------------------------------------------- 1 | namespace Lambdajection.CustomResource 2 | { 3 | /// 4 | /// Describes output data concerning a custom resource 5 | /// and/or its related entities. 6 | /// 7 | public interface ICustomResourceOutputData 8 | { 9 | /// 10 | /// Gets the ID / PhysicalResourceId associated with the custom resource. 11 | /// 12 | /// The resulting custom resource's physicalResourceId. 13 | string Id { get; } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/Encryption/EncryptedAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | 4 | namespace Lambdajection.Encryption 5 | { 6 | /// 7 | /// Attribute used to indicate an encrypted property. Properties annotated with this 8 | /// are decrypted on startup. 9 | /// 10 | [AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] 11 | [Conditional("CodeGeneration")] 12 | public class EncryptedAttribute : Attribute 13 | { 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/Encryption/Encryption.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netstandard2.1 5 | Lambdajection.Encryption 6 | $(PackageId) 7 | Provides an attribute and decryption service for encrypted configuration options that are injected into AWS Lambdas. 8 | true 9 | snupkg 10 | true 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /src/Encryption/IDecryptionService.cs: -------------------------------------------------------------------------------- 1 | using System.Threading; 2 | using System.Threading.Tasks; 3 | 4 | namespace Lambdajection.Encryption 5 | { 6 | /// 7 | /// Describes a service to decrypt values. 8 | /// 9 | public interface IDecryptionService 10 | { 11 | /// 12 | /// Decrypts a value. 13 | /// 14 | /// The value to be decrypted. 15 | /// Token to cancel the operation with. 16 | /// The decrypted value. 17 | Task Decrypt(string ciphertext, CancellationToken cancellationToken = default); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/Encryption/build/Lambdajection.Encryption.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | $(MSBuildThisFileDirectory)..\lib\netstandard2.1\Lambdajection.Encryption.dll,$(LambdajectionBuildTimeAssemblies) 4 | 5 | -------------------------------------------------------------------------------- /src/Framework.BuildTime/AnalyzerResults.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | using Microsoft.CodeAnalysis; 4 | 5 | #pragma warning disable CA1032, SA1600, CS8618, CS1591 6 | 7 | namespace Lambdajection.Framework 8 | { 9 | internal class AnalyzerResults 10 | { 11 | public INamedTypeSymbol? InputType { get; set; } 12 | 13 | public string? InputTypeName { get; set; } 14 | 15 | public INamedTypeSymbol? InputEncapsulationType { get; set; } 16 | 17 | public string? InputEncapsulationTypeName { get; set; } 18 | 19 | public string? OutputTypeName { get; set; } 20 | 21 | public IEnumerable GeneratedMethods { get; set; } 22 | 23 | public INamedTypeSymbol? FlattenedInputType => InputEncapsulationType != null && InputType != null 24 | ? InputEncapsulationType.ConstructedFrom.Construct(InputType) 25 | : InputType; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/Framework.BuildTime/GeneratedMethodInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection; 3 | 4 | using Microsoft.CodeAnalysis; 5 | 6 | #pragma warning disable CA1032, SA1600, CS8618, CS1591 7 | 8 | namespace Lambdajection.Framework 9 | { 10 | internal class GeneratedMethodInfo 11 | { 12 | public GeneratedAttribute GeneratedAttribute { get; set; } 13 | 14 | public IMethodSymbol GeneratedMethod { get; set; } 15 | 16 | public Location Location { get; set; } 17 | 18 | #pragma warning disable IDE0046 19 | public IMemberGenerator GetGenerator(AnalyzerResults analyzerResults, GenerationContext context) 20 | { 21 | var assembly = Assembly.Load(GeneratedAttribute.AssemblyName); 22 | var type = assembly?.GetType(GeneratedAttribute.TypeName); 23 | 24 | if (type == null) 25 | { 26 | throw new GenerationFailureException 27 | { 28 | Id = "LJ0004", 29 | Title = "Member Generator Not Found", 30 | Description = $"Lambdajection was unable to load member generator: {GeneratedAttribute.TypeName} from {GeneratedAttribute.AssemblyName}", 31 | Location = Location, 32 | }; 33 | } 34 | 35 | return (IMemberGenerator)Activator.CreateInstance(type, new object[] { analyzerResults, context }); 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/Framework.BuildTime/GenerationContext.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Threading; 3 | 4 | using Microsoft.CodeAnalysis; 5 | using Microsoft.CodeAnalysis.CSharp.Syntax; 6 | 7 | #pragma warning disable SA1600, CS8618 8 | 9 | namespace Lambdajection.Framework 10 | { 11 | internal class GenerationContext 12 | { 13 | public ClassDeclarationSyntax Declaration { get; init; } 14 | 15 | public Compilation Compilation { get; init; } 16 | 17 | public SyntaxTree SyntaxTree { get; init; } 18 | 19 | public SemanticModel SemanticModel { get; init; } 20 | 21 | public AttributeData AttributeData { get; init; } 22 | 23 | public GeneratorExecutionContext SourceGeneratorContext { get; set; } 24 | 25 | public CancellationToken CancellationToken { get; set; } 26 | 27 | public INamedTypeSymbol StartupType { get; init; } 28 | 29 | public INamedTypeSymbol? SerializerType { get; set; } 30 | 31 | public INamedTypeSymbol? ConfigFactoryType { get; set; } 32 | 33 | public string StartupTypeName { get; set; } 34 | 35 | public string StartupTypeDisplayName { get; set; } 36 | 37 | public string RunnerMethodName { get; set; } 38 | 39 | public HashSet Usings { get; } = new HashSet(); 40 | 41 | public GenerationSettings Settings { get; init; } 42 | 43 | public HashSet ExtraIamPermissionsRequired { get; init; } = new HashSet(); 44 | 45 | internal LambdaInterfaceAttribute LambdaInterfaceAttribute { get; init; } 46 | 47 | internal LambdaHostAttribute LambdaHostAttribute { get; init; } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/Framework.BuildTime/GenerationFailureException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | using Microsoft.CodeAnalysis; 4 | 5 | #pragma warning disable CA1032, SA1600, CS8618, CS1591 6 | 7 | namespace Lambdajection.Framework 8 | { 9 | internal class GenerationFailureException : Exception 10 | { 11 | public string Id { get; init; } 12 | 13 | public string Title { get; init; } 14 | 15 | public string Description { get; init; } 16 | 17 | public string Category { get; init; } = "Lambdajection"; 18 | 19 | public Location Location { get; init; } 20 | 21 | public Diagnostic Diagnostic => 22 | Diagnostic.Create(new DiagnosticDescriptor(Id, Title, Description, Category, DiagnosticSeverity.Error, true), Location); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/Framework.BuildTime/IMemberGenerator.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.CodeAnalysis.CSharp.Syntax; 2 | 3 | namespace Lambdajection.Framework 4 | { 5 | /// 6 | /// Interface to describe generators that generate class members. 7 | /// 8 | internal interface IMemberGenerator 9 | { 10 | /// 11 | /// Generate a class member. 12 | /// 13 | /// The generated class member. 14 | MemberDeclarationSyntax GenerateMember(); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/Framework.BuildTime/build/Lambdajection.Framework.BuildTime.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | $(MSBuildThisFileDirectory)..\tools\any\Lambdajection.Framework.BuildTime.dll,$(LambdajectionBuildTimeAssemblies) 4 | 5 | -------------------------------------------------------------------------------- /src/Framework/Framework.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netstandard2.1 5 | Lambdajection.Framework 6 | NU5128;NU5131 7 | $(PackageId) 8 | true 9 | Includes attributes that provide a framework for generating Lambdas with Lambdajection. 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /src/Framework/GeneratedAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Lambdajection.Framework 4 | { 5 | /// 6 | /// Attribute used to denote methods that are generated by the Lambdajection Generator. 7 | /// 8 | [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)] 9 | internal class GeneratedAttribute : Attribute 10 | { 11 | /// 12 | /// Initializes a new instance of the class. 13 | /// 14 | /// Name of the assembly where to find the generator for generating the attributed method. 15 | /// Name of the type where to find the generator for generating the attributed method. 16 | public GeneratedAttribute(string assemblyName, string typeName) 17 | { 18 | AssemblyName = assemblyName; 19 | TypeName = typeName; 20 | } 21 | 22 | /// 23 | /// Gets the name of the assembly where to find the generator for generating the attributed method. 24 | /// 25 | public string AssemblyName { get; } 26 | 27 | /// 28 | /// Gets the name of the type of generator to use for generating the attributed method. 29 | /// 30 | public string TypeName { get; } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/Framework/Internal/IsExternalInit.cs: -------------------------------------------------------------------------------- 1 | namespace System.Runtime.CompilerServices 2 | { 3 | #pragma warning disable CS1591, SA1600 4 | public static class IsExternalInit 5 | { 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/Framework/LambdaHostAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Lambdajection.Framework 4 | { 5 | /// 6 | /// Build-time only attribute to help determine what lambda host to use 7 | /// for an attribute. 8 | /// 9 | [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)] 10 | internal class LambdaHostAttribute : Attribute 11 | { 12 | /// 13 | /// Initializes a new instance of the class. 14 | /// 15 | /// The assembly the host is located in. 16 | /// The name of the host class. 17 | public LambdaHostAttribute(string assemblyName, string className) 18 | { 19 | AssemblyName = assemblyName; 20 | ClassName = className; 21 | } 22 | 23 | /// 24 | /// Gets the assembly name the lambda host class is located in. 25 | /// 26 | /// The name of the assembly where the lambda host class is located. 27 | public string AssemblyName { get; } 28 | 29 | /// 30 | /// Gets the name of the lambda host class. 31 | /// 32 | /// The name of the lambda host class. 33 | public string ClassName { get; } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/Framework/LambdaInterfaceAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Lambdajection.Framework 4 | { 5 | /// 6 | /// Build-time only attribute to help determine what interface to apply to a Lambda. 7 | /// 8 | [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)] 9 | internal class LambdaInterfaceAttribute : Attribute 10 | { 11 | /// 12 | /// Initializes a new instance of the class. 13 | /// 14 | /// The assembly the interface is located in. 15 | /// The name of the interface. 16 | public LambdaInterfaceAttribute(string assemblyName, string interfaceName) 17 | { 18 | AssemblyName = assemblyName; 19 | InterfaceName = interfaceName; 20 | } 21 | 22 | /// 23 | /// Gets the assembly name the lambda parameter delegate assembly. 24 | /// 25 | /// The name of the assembly where the lambda parameter delegate is located. 26 | public string AssemblyName { get; } 27 | 28 | /// 29 | /// Gets the name of the lambda interface. 30 | /// 31 | /// The name of the lambda interface. 32 | public string InterfaceName { get; } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/Framework/LambdajectionVersionAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Lambdajection.Framework 4 | { 5 | /// 6 | /// Attribute for annotating assemblies with the lambdajection package version. 7 | /// 8 | [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = false, Inherited = false)] 9 | public class LambdajectionVersionAttribute : Attribute 10 | { 11 | /// 12 | /// Initializes a new instance of the class. 13 | /// 14 | /// Version of the lambdajection package. 15 | public LambdajectionVersionAttribute(string version) 16 | { 17 | Version = version; 18 | } 19 | 20 | /// 21 | /// Gets the version of the Lambdajection package. 22 | /// 23 | public string Version { get; } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/Framework/NotValidatedAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Lambdajection.Framework 4 | { 5 | /// 6 | /// Attribute to annotate properties that are not validated. 7 | /// 8 | [AttributeUsage(AttributeTargets.Property)] 9 | public class NotValidatedAttribute : Attribute 10 | { 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/Framework/RequiresIamPermissionAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Lambdajection.Framework 4 | { 5 | /// 6 | /// An attribute to annotate methods with required iam permissions needed for successfully invoking the method. 7 | /// 8 | [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)] 9 | public class RequiresIamPermissionAttribute : Attribute 10 | { 11 | /// 12 | /// Initializes a new instance of the class. 13 | /// 14 | /// The required IAM permission for the call. 15 | public RequiresIamPermissionAttribute(string permission) 16 | { 17 | Permission = permission; 18 | } 19 | 20 | /// 21 | /// Gets the permission required for this call. 22 | /// 23 | public string Permission { get; } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/Framework/build/Lambdajection.Framework.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | true 4 | $(MSBuildThisFileDirectory)..\lib\netstandard2.1\Lambdajection.Framework.dll,$(LambdajectionBuildTimeAssemblies) 5 | 6 | -------------------------------------------------------------------------------- /src/Generator/Attributes/AttributeFactory.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.Reflection; 4 | 5 | using Microsoft.CodeAnalysis; 6 | 7 | namespace Lambdajection.Generator.Attributes 8 | { 9 | public static class AttributeFactory 10 | { 11 | public static T Create(AttributeData attributeData) 12 | { 13 | var parameters = from arg in attributeData.ConstructorArguments 14 | select arg.Value; 15 | 16 | var result = (T?)Activator.CreateInstance(typeof(T), parameters.ToArray()); 17 | foreach (var (key, constant) in attributeData.NamedArguments) 18 | { 19 | var value = constant.Value; 20 | var prop = typeof(T).GetProperty(key, BindingFlags.Instance | BindingFlags.Public); 21 | var setter = prop?.GetSetMethod(true); 22 | setter?.Invoke(result, new[] { value }); 23 | } 24 | 25 | return result == null 26 | ? throw new Exception("Could not create attribute from attributedata") 27 | : result; 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/Generator/AwsServiceMetadata.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Lambdajection.Generator 4 | { 5 | public readonly struct AwsServiceMetadata : IEquatable 6 | { 7 | public AwsServiceMetadata(string serviceName, string interfaceName, string implementationName, string namespaceName) 8 | { 9 | ServiceName = serviceName; 10 | InterfaceName = interfaceName; 11 | ImplementationName = implementationName; 12 | NamespaceName = namespaceName; 13 | } 14 | 15 | public string ServiceName { get; } 16 | 17 | public string InterfaceName { get; } 18 | 19 | public string ImplementationName { get; } 20 | 21 | public string NamespaceName { get; } 22 | 23 | public static bool operator ==(AwsServiceMetadata metadataA, AwsServiceMetadata metadataB) 24 | { 25 | return metadataA.Equals(metadataB); 26 | } 27 | 28 | public static bool operator !=(AwsServiceMetadata metadataA, AwsServiceMetadata metadataB) 29 | { 30 | return !metadataA.Equals(metadataB); 31 | } 32 | 33 | public override bool Equals(object? obj) 34 | { 35 | return obj is AwsServiceMetadata result && result.ServiceName.Equals(ServiceName, StringComparison.OrdinalIgnoreCase); 36 | } 37 | 38 | public bool Equals(AwsServiceMetadata result) 39 | { 40 | return result.ServiceName.Equals(ServiceName, StringComparison.OrdinalIgnoreCase); 41 | } 42 | 43 | public override int GetHashCode() 44 | { 45 | return ServiceName.GetHashCode(StringComparison.OrdinalIgnoreCase); 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/Generator/GeneratorHost.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading; 3 | using System.Threading.Tasks; 4 | 5 | using Microsoft.Extensions.DependencyInjection; 6 | using Microsoft.Extensions.Hosting; 7 | 8 | namespace Lambdajection.Generator 9 | { 10 | public class GeneratorHost : IHost 11 | { 12 | public GeneratorHost(IServiceProvider services) 13 | { 14 | Services = services; 15 | } 16 | 17 | public IServiceProvider Services { get; } 18 | 19 | public async Task StartAsync(CancellationToken cancellationToken = default) 20 | { 21 | await Task.CompletedTask; 22 | 23 | var unitGenerator = Services.GetRequiredService(); 24 | unitGenerator.Generate(); 25 | 26 | var lifetime = Services.GetRequiredService(); 27 | lifetime.StopApplication(); 28 | } 29 | 30 | public Task StopAsync(CancellationToken cancellationToken = default) 31 | { 32 | return Task.CompletedTask; 33 | } 34 | 35 | public void Dispose() 36 | { 37 | GC.SuppressFinalize(this); 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/Generator/Internal/IsExternalInit.cs: -------------------------------------------------------------------------------- 1 | namespace System.Runtime.CompilerServices 2 | { 3 | public static class IsExternalInit 4 | { 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/Generator/ProgramContext.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | using Lambdajection.Generator.TemplateGeneration; 4 | 5 | using Microsoft.CodeAnalysis; 6 | 7 | namespace Lambdajection.Generator 8 | { 9 | public class ProgramContext 10 | { 11 | public GeneratorExecutionContext GeneratorExecutionContext { get; set; } 12 | 13 | public List LambdaInfos { get; set; } = new List(); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/Generator/ProgramHost.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.CodeAnalysis; 2 | using Microsoft.Extensions.DependencyInjection; 3 | using Microsoft.Extensions.Hosting; 4 | using Microsoft.Extensions.Logging; 5 | 6 | namespace Lambdajection.Generator 7 | { 8 | public class ProgramHost 9 | { 10 | public void Run(GeneratorExecutionContext context) 11 | { 12 | Host.CreateDefaultBuilder() 13 | .ConfigureServices((builderContext, services) => 14 | { 15 | services.AddSingleton(new ProgramContext { GeneratorExecutionContext = context }); 16 | services.AddSingleton(); 17 | new Startup().ConfigureServices(services); 18 | 19 | services.AddLogging(options => 20 | { 21 | options.ClearProviders(); 22 | options.AddConsole(); 23 | }); 24 | }) 25 | .Build() 26 | .RunAsync(context.CancellationToken) 27 | .GetAwaiter() 28 | .GetResult(); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/Generator/Startup.cs: -------------------------------------------------------------------------------- 1 | using Lambdajection.Framework.Utils; 2 | 3 | using Microsoft.Extensions.DependencyInjection; 4 | 5 | namespace Lambdajection.Generator 6 | { 7 | public class Startup 8 | { 9 | public void ConfigureServices(IServiceCollection services) 10 | { 11 | services.AddSingleton(); 12 | services.AddSingleton(); 13 | services.AddSingleton(); 14 | services.AddSingleton(); 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/Generator/TemplateGeneration/Converters/GetAttTagConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | using YamlDotNet.Core; 4 | using YamlDotNet.Core.Events; 5 | using YamlDotNet.Serialization; 6 | 7 | namespace Lambdajection.Generator.TemplateGeneration 8 | { 9 | public class GetAttTagConverter : IYamlTypeConverter 10 | { 11 | public bool Accepts(Type type) 12 | { 13 | return type == typeof(GetAttTag); 14 | } 15 | 16 | public object ReadYaml(IParser parser, Type type) 17 | { 18 | parser.MoveNext(); 19 | return new GetAttTag(); 20 | } 21 | 22 | public void WriteYaml(IEmitter emitter, object? value, Type type) 23 | { 24 | var result = (GetAttTag)value!; 25 | emitter.Emit(new Scalar( 26 | null, 27 | "!GetAtt", 28 | $"{result.Name}.{result.Attribute}", 29 | ScalarStyle.Plain, 30 | false, 31 | false 32 | )); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/Generator/TemplateGeneration/Converters/SubTagConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | using YamlDotNet.Core; 4 | using YamlDotNet.Core.Events; 5 | using YamlDotNet.Serialization; 6 | 7 | namespace Lambdajection.Generator.TemplateGeneration 8 | { 9 | public class SubTagConverter : IYamlTypeConverter 10 | { 11 | public bool Accepts(Type type) 12 | { 13 | return type == typeof(SubTag); 14 | } 15 | 16 | public object ReadYaml(IParser parser, Type type) 17 | { 18 | parser.MoveNext(); 19 | return new SubTag(); 20 | } 21 | 22 | public void WriteYaml(IEmitter emitter, object? value, Type type) 23 | { 24 | var result = (SubTag)value!; 25 | emitter.Emit(new Scalar( 26 | null, 27 | "!Sub", 28 | $"{result.Expression}", 29 | ScalarStyle.Plain, 30 | false, 31 | false 32 | )); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/Generator/TemplateGeneration/Models/Export.cs: -------------------------------------------------------------------------------- 1 | namespace Lambdajection.Generator.TemplateGeneration 2 | { 3 | public class Export 4 | { 5 | public object Name { get; set; } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/Generator/TemplateGeneration/Models/GetAttTag.cs: -------------------------------------------------------------------------------- 1 | namespace Lambdajection.Generator.TemplateGeneration 2 | { 3 | public class GetAttTag 4 | { 5 | public GetAttTag() 6 | { 7 | } 8 | 9 | public string Name { get; set; } 10 | 11 | public string Attribute { get; set; } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/Generator/TemplateGeneration/Models/LambdaInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Lambdajection.Generator.TemplateGeneration 4 | { 5 | public class LambdaInfo 6 | { 7 | public string ClassName { get; set; } 8 | 9 | public string FullyQualifiedClassName { get; set; } 10 | 11 | public HashSet Permissions { get; set; } 12 | 13 | public bool EnableTracing { get; set; } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/Generator/TemplateGeneration/Models/Output.cs: -------------------------------------------------------------------------------- 1 | namespace Lambdajection.Generator.TemplateGeneration 2 | { 3 | public class Output 4 | { 5 | public Output(object value, object name) 6 | { 7 | Value = value; 8 | Export = new Export { Name = name }; 9 | } 10 | 11 | public object Value { get; set; } 12 | 13 | public Export Export { get; set; } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/Generator/TemplateGeneration/Models/Policy.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Lambdajection.Generator.TemplateGeneration 4 | { 5 | public class Policy 6 | { 7 | public Policy(string policyName) 8 | { 9 | PolicyName = policyName; 10 | } 11 | 12 | public string PolicyName { get; set; } 13 | 14 | public PolicyDocument PolicyDocument { get; private set; } = new PolicyDocument(); 15 | 16 | public Policy AddStatement(HashSet action, string effect = "Allow", string resource = "*") 17 | { 18 | PolicyDocument.Statement.Add(new PolicyStatement() 19 | { 20 | Effect = effect, 21 | Action = action, 22 | Resource = resource, 23 | Principal = null, 24 | }); 25 | 26 | return this; 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Generator/TemplateGeneration/Models/PolicyDocument.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Lambdajection.Generator.TemplateGeneration 4 | { 5 | public class PolicyDocument 6 | { 7 | public string Version { get; set; } = "2012-10-17"; 8 | 9 | public List Statement { get; set; } = new List(); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/Generator/TemplateGeneration/Models/PolicyStatement.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Lambdajection.Generator.TemplateGeneration 4 | { 5 | public class PolicyStatement 6 | { 7 | public string Effect { get; set; } 8 | 9 | public HashSet Action { get; set; } 10 | 11 | public string Resource { get; set; } 12 | 13 | public Principal? Principal { get; set; } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/Generator/TemplateGeneration/Models/Principal.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Lambdajection.Generator.TemplateGeneration 4 | { 5 | public class Principal 6 | { 7 | public HashSet AWS { get; set; } 8 | 9 | public HashSet Service { get; set; } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/Generator/TemplateGeneration/Models/Resource.cs: -------------------------------------------------------------------------------- 1 | namespace Lambdajection.Generator 2 | { 3 | public class Resource 4 | { 5 | public virtual string Type { get; set; } 6 | 7 | public virtual object Properties { get; set; } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/Generator/TemplateGeneration/Models/SubTag.cs: -------------------------------------------------------------------------------- 1 | namespace Lambdajection.Generator.TemplateGeneration 2 | { 3 | public class SubTag 4 | { 5 | public SubTag() 6 | { 7 | } 8 | 9 | public string Expression { get; set; } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/Generator/TypeExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | internal static class TypeExtensions 4 | { 5 | public static TReturnType? GetPublicProperty(this object @this, string propertyName) 6 | { 7 | var property = @this.GetType().GetProperty(propertyName); 8 | var propertyGetter = property.GetGetMethod(); 9 | return (TReturnType?)propertyGetter.Invoke(@this, Array.Empty()); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/Generator/build/Lambdajection.Generator.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | $(RestorePackagesPath) 4 | 5 | -------------------------------------------------------------------------------- /src/Layer/Layer.template.yml: -------------------------------------------------------------------------------- 1 | Description: Lambda Layer for Lambdajection 2 | Transform: AWS::Serverless-2016-10-31 3 | Metadata: 4 | AWS::ServerlessRepo::Application: 5 | Name: lambdajection-layer 6 | Description: Lambda Layer containing a .NET Runtime Package Store of Lambdajection and its dependencies. 7 | Author: Cythral LLC 8 | SpdxLicenseId: MIT 9 | LicenseUrl: ./layer/LICENSE.txt 10 | ReadmeUrl: ./layer/README.md 11 | Labels: 12 | - lambda 13 | - dotnet 14 | - layer 15 | - dependency-injection 16 | - lambdajection 17 | HomePageUrl: https://github.com/cythral/lambdajection 18 | SourceCodeUrl: https://github.com/cythral/lambdajection 19 | 20 | Resources: 21 | Layer: 22 | Type: AWS::Serverless::LayerVersion 23 | Properties: 24 | LayerName: lambdajection 25 | Description: Lambda Layer for Lambajection 26 | CompatibleRuntimes: 27 | - provided.al2 28 | CompatibleArchitectures: 29 | - x86_64 30 | - arm64 31 | ContentUri: ./layer 32 | LicenseInfo: MIT 33 | 34 | Outputs: 35 | LayerArn: 36 | Description: ARN of the Lambdajection Layer 37 | Value: !Ref Layer 38 | -------------------------------------------------------------------------------- /src/Layer/build/Lambdajection.Layer.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | $(MSBuildThisFileDirectory)..\content\artifact.xml 4 | $(TargetManifestFiles);$(LayerManifestFile) 5 | 6 | -------------------------------------------------------------------------------- /src/Metapackage/Metapackage.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | netstandard2.1 4 | false 5 | Lambdajection 6 | $(PackageId) 7 | NU5128 8 | Write AWS Lambda Functions using Dependency Injection. 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /src/Metapackage/build/Lambdajection.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | true 4 | true 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/Metapackage/build/Lambdajection.targets: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5.0.100 4 | Lambdajection_AddAdditionalFiles;$(BeforeBuild) 5 | Lambdajection_MinimumSdkRequirement;$(CoreCompileDependsOn) 6 | $(IntermediateOutputPath) 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/Runtime/Runtime.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | netstandard2.1 4 | false 5 | Lambdajection.Runtime 6 | $(PackageId) 7 | NU5128 8 | true 9 | Sets Lambdajection projects up to support custom runtimes. 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /src/Runtime/build/Lambdajection.Runtime.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | Exe 4 | true 5 | bootstrap 6 | 7 | -------------------------------------------------------------------------------- /src/Sns/ISnsEventHandler.cs: -------------------------------------------------------------------------------- 1 | using System.Threading; 2 | using System.Threading.Tasks; 3 | 4 | using Lambdajection.Framework; 5 | 6 | namespace Lambdajection.Sns 7 | { 8 | /// 9 | /// Describes an Amazon Lambda function. 10 | /// 11 | /// The type of the lambda's input parameter. 12 | /// The type of the lambda's return value. 13 | public interface ISnsEventHandler 14 | { 15 | /// 16 | /// The lambda's entrypoint. 17 | /// 18 | /// The lambda's input parameter. 19 | /// Token used to cancel the operation. 20 | /// The lambda's return value. 21 | Task Handle(SnsMessage parameter, CancellationToken cancellationToken = default); 22 | 23 | /// 24 | /// Runs validations the lambda's input parameter. 25 | /// 26 | /// The lambda's input parameter. 27 | [Generated("Lambdajection.Generator", "Lambdajection.Generator.ValidationsGenerator")] 28 | void Validate(SnsMessage parameter); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/Sns/Models/SnsEvent.cs: -------------------------------------------------------------------------------- 1 | namespace Lambdajection.Sns 2 | { 3 | /// 4 | /// Simple Notification Service Event. 5 | /// 6 | /// The type of message contained within the SNS Event. 7 | public class SnsEvent 8 | { 9 | /// 10 | /// Initializes a new instance of the class. 11 | /// 12 | /// The records that belong to the event. 13 | public SnsEvent( 14 | SnsRecord[] records 15 | ) 16 | { 17 | Records = records; 18 | } 19 | 20 | /// 21 | /// Gets or sets the records that are a part of this event. 22 | /// 23 | public SnsRecord[] Records { get; set; } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/Sns/Models/SnsMessageAttribute.cs: -------------------------------------------------------------------------------- 1 | namespace Lambdajection.Sns 2 | { 3 | /// 4 | /// An SNS message attribute. 5 | /// 6 | public class SnsMessageAttribute 7 | { 8 | /// 9 | /// Initializes a new instance of the class. 10 | /// 11 | /// The attribute's data type. 12 | /// The attribute's value. 13 | public SnsMessageAttribute(string type, string value) 14 | { 15 | Type = type; 16 | Value = value; 17 | } 18 | 19 | /// 20 | /// Gets or sets the attribute type. 21 | /// 22 | public string Type { get; set; } 23 | 24 | /// 25 | /// Gets or sets the attribute value. 26 | /// 27 | public string Value { get; set; } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Sns/Sns.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | netstandard2.1 4 | Lambdajection.Sns 5 | $(PackageId) 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /src/Tracing/Tracing.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | netstandard2.1 4 | Lambdajection.Tracing 5 | $(PackageId) 6 | NU5128 7 | false 8 | true 9 | Adds X-Ray Tracing Support to Lambdajection. 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /src/Tracing/build/Lambdajection.Tracing.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | true 4 | 5 | -------------------------------------------------------------------------------- /stylecop.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json", 3 | "settings": { 4 | "layoutRules": { 5 | "newlineAtEndOfFile": "require" 6 | } 7 | } 8 | } -------------------------------------------------------------------------------- /templates/Directory.Build.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | true 4 | $(MSBuildThisFileDirectory)..\bin\Examples\$(MSBuildProjectName)\$(Configuration) 5 | $(MSBuildThisFileDirectory)..\obj\Templates\$(MSBuildProjectName) 6 | $(MSBuildThisFileDirectory)..\bin\Packages\Templates\$(Configuration) 7 | $(MSBuildThisFileDirectory)..\.nuget\templates 8 | <_PackagesDebug>$(MSBuildThisFileDirectory)..\bin\Packages\Debug 9 | <_PackagesRelease>$(MSBuildThisFileDirectory)..\bin\Packages\Release 10 | @(CustomLocalFeed);$(RestoreAdditionalProjectSources) 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /templates/Options/.excludecsproj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cythral/lambdajection/eb2e07d3f83f9624c1a315f199b2ba3b567f1c79/templates/Options/.excludecsproj -------------------------------------------------------------------------------- /templates/Options/Options.cs: -------------------------------------------------------------------------------- 1 | using Lambdajection.Attributes; 2 | #if encryption 3 | using Lambdajection.Encryption; 4 | #endif 5 | 6 | namespace __Project__ 7 | { 8 | [LambdaOptions(typeof(Handler), "SectionName")] 9 | public class __Options__ 10 | { 11 | #if encryption 12 | [Encrypted] 13 | #endif 14 | public string Value { get; set; } = ""; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /templates/Options/Options.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net6.0 5 | 8.0 6 | enable 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /templates/Project/.template.config/template.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json.schemastore.org/template", 3 | "identity": "Lambdajection.Templates.Lambda", 4 | "author": "Cythral LLC", 5 | "classifications": [ 6 | "Cloud", 7 | "Lambda" 8 | ], 9 | "name": "AWS Lambda using Lambdajection", 10 | "shortName": "lambdajection", 11 | "tags": { 12 | "language": "C#", 13 | "type": "project" 14 | }, 15 | "symbols": { 16 | "namespace": { 17 | "type": "parameter", 18 | "description": "Namespace for the Lambda project", 19 | "replaces": "__Project__", 20 | "FileRename": "Project", 21 | "defaultValue": "Project" 22 | }, 23 | "version": { 24 | "type": "parameter", 25 | "description": "Version of Lambdajection to use", 26 | "replaces": "$(LambdajectionVersion)", 27 | "defaultValue": "__LambdajectionVersion__" 28 | }, 29 | "encryption": { 30 | "type": "parameter", 31 | "description": "Whether to include the Encryption package", 32 | "datatype": "bool", 33 | "defaultValue": "false" 34 | }, 35 | "disposable": { 36 | "type": "parameter", 37 | "description": "Whether or not the Lambda uses unmanaged resources", 38 | "datatype": "bool", 39 | "defaultValue": "false" 40 | } 41 | } 42 | } -------------------------------------------------------------------------------- /templates/Project/Handler.cs: -------------------------------------------------------------------------------- 1 | using System.Threading; 2 | using System.Threading.Tasks; 3 | 4 | using Amazon.Lambda.Core; 5 | 6 | using Lambdajection.Attributes; 7 | 8 | namespace __Project__ 9 | { 10 | [Lambda(typeof(Startup))] 11 | #if disposable 12 | public partial class Handler : IAsyncDisposable, IDisposable 13 | #else 14 | public partial class Handler 15 | #endif 16 | { 17 | #if disposable 18 | private bool disposed; 19 | 20 | #endif 21 | public async Task Handle(object request, CancellationToken cancellationToken = default) 22 | { 23 | return await Task.FromResult(new { }); 24 | } 25 | #if disposable 26 | 27 | #region Disposable Methods 28 | public async ValueTask DisposeAsync() 29 | { 30 | await DisposeAsyncCore(); 31 | Dispose(false); 32 | GC.SuppressFinalize(this); 33 | } 34 | 35 | public void Dispose() 36 | { 37 | Dispose(true); 38 | GC.SuppressFinalize(this); 39 | } 40 | 41 | protected virtual async ValueTask DisposeAsyncCore() 42 | { 43 | await Task.CompletedTask; 44 | // Perform asynchronous cleanup here 45 | } 46 | 47 | protected virtual void Dispose(bool disposing) 48 | { 49 | if (disposed) 50 | { 51 | return; 52 | } 53 | 54 | if (disposing) 55 | { 56 | // Perform synchronous cleanup here 57 | } 58 | 59 | disposed = true; 60 | } 61 | #endregion 62 | #endif 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /templates/Project/Project.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net6.0 5 | 9.0 6 | enable 7 | __Project__ 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /templates/Project/Startup.cs: -------------------------------------------------------------------------------- 1 | using Lambdajection.Core; 2 | 3 | using Microsoft.Extensions.Configuration; 4 | using Microsoft.Extensions.DependencyInjection; 5 | 6 | namespace __Project__ 7 | { 8 | public class Startup : ILambdaStartup 9 | { 10 | private readonly IConfiguration configuration; 11 | 12 | public Startup(IConfiguration configuration) 13 | { 14 | this.configuration = configuration; 15 | } 16 | 17 | public void ConfigureServices(IServiceCollection services) 18 | { 19 | // Inject services into the Lambda's container here 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /tests/Common/AsyncDisposableLambda.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | 4 | namespace Lambdajection 5 | { 6 | #pragma warning disable CA1063,CA1816 7 | public class AsyncDisposableLambda : TestLambda, IAsyncDisposable 8 | { 9 | public virtual async ValueTask DisposeAsync() 10 | { 11 | await Task.CompletedTask; 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /tests/Common/AutoAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Reflection; 4 | using System.Text.Json; 5 | using System.Text.Json.Serialization; 6 | 7 | using Amazon.Runtime.Internal.Util; 8 | 9 | using AutoFixture; 10 | using AutoFixture.AutoNSubstitute; 11 | using AutoFixture.NUnit3; 12 | 13 | using NSubstitute; 14 | 15 | internal class AutoAttribute : AutoDataAttribute 16 | { 17 | public AutoAttribute(Type? customizer = null) 18 | : base(() => Create(fixture => customizer?.GetMethod("Customize", BindingFlags.Static | BindingFlags.Public)!.Invoke(null, new object[] { fixture }))) 19 | { 20 | } 21 | 22 | public static IFixture Create(Action customize) 23 | { 24 | var fixture = new Fixture(); 25 | fixture.Register(() => new JsonSerializerOptions()); 26 | fixture.Customize(new AutoNSubstituteCustomization()); 27 | fixture.Inject(Substitute.For()); 28 | fixture.Customizations.Insert(-1, new TargetRelay()); 29 | fixture.Customizations.Add(new TypeOmitter>()); 30 | fixture.Customizations.Add(new TypeOmitter()); 31 | customize(fixture); 32 | return fixture; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /tests/Common/DisposableLambda.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Lambdajection 4 | { 5 | #pragma warning disable CA1063,CA1816 6 | public class DisposableLambda : TestLambda, IDisposable 7 | { 8 | public virtual void Dispose() 9 | { 10 | // do nothing 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /tests/Common/MultiDisposableLambda.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | 4 | namespace Lambdajection 5 | { 6 | #pragma warning disable CA1063,CA1816 7 | public class MultiDisposableLambda : TestLambda, IAsyncDisposable, IDisposable 8 | { 9 | public virtual async ValueTask DisposeAsync() 10 | { 11 | await Task.CompletedTask; 12 | } 13 | 14 | public virtual void Dispose() 15 | { 16 | // do nothing 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /tests/Common/TargetAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Reflection; 5 | 6 | [AttributeUsage(AttributeTargets.Parameter)] 7 | public class TargetAttribute : Attribute 8 | { 9 | public TargetAttribute(Type? overridesType = null, string? overridesMemberName = null) 10 | { 11 | if (overridesType == null || overridesMemberName == null) 12 | { 13 | return; 14 | } 15 | 16 | var fieldsQuery = from member in overridesType.GetFields(BindingFlags.Static | BindingFlags.Public) 17 | where member.Name == overridesMemberName 18 | select member; 19 | 20 | var value = (Dictionary?)fieldsQuery.First().GetValue(null!); 21 | Overrides = value ?? Overrides; 22 | } 23 | 24 | public Dictionary Overrides { get; } = new Dictionary(); 25 | } 26 | -------------------------------------------------------------------------------- /tests/Common/TestConfigFactory.cs: -------------------------------------------------------------------------------- 1 | using Lambdajection.Core; 2 | 3 | using Microsoft.Extensions.Configuration; 4 | 5 | namespace Lambdajection 6 | { 7 | public class TestConfigFactory : ILambdaConfigFactory 8 | { 9 | #pragma warning disable CA1822 10 | public IConfigurationRoot Create() 11 | { 12 | return new ConfigurationBuilder().Build(); 13 | } 14 | #pragma warning restore CA1822 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /tests/Common/TestConfigurator.cs: -------------------------------------------------------------------------------- 1 | using Lambdajection.Core; 2 | 3 | using Microsoft.Extensions.Configuration; 4 | using Microsoft.Extensions.DependencyInjection; 5 | 6 | namespace Lambdajection 7 | { 8 | public class TestConfigurator : ILambdaConfigurator 9 | { 10 | public IConfiguration Configuration { get; set; } = null!; 11 | 12 | public IServiceCollection ServicesSetByConfigureOptions { get; private set; } = null!; 13 | 14 | public IServiceCollection ServicesSetByConfigureAwsServices { get; private set; } = null!; 15 | 16 | public void ConfigureOptions(IConfiguration configuration, IServiceCollection services) 17 | { 18 | Configuration = configuration; 19 | ServicesSetByConfigureOptions = services; 20 | } 21 | 22 | public void ConfigureAwsServices(IServiceCollection services) 23 | { 24 | ServicesSetByConfigureAwsServices = services; 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /tests/Common/TestCustomResourceLambda.cs: -------------------------------------------------------------------------------- 1 | using System.Threading; 2 | using System.Threading.Tasks; 3 | 4 | using Lambdajection.CustomResource; 5 | 6 | namespace Lambdajection 7 | { 8 | public class TestCustomResourceLambda : ICustomResourceProvider 9 | { 10 | public virtual Task Create(CustomResourceRequest request, CancellationToken cancellationToken) 11 | { 12 | return Task.FromResult((TestCustomResourceOutputData)null!); 13 | } 14 | 15 | public virtual Task Update(CustomResourceRequest request, CancellationToken cancellationToken) 16 | { 17 | return Task.FromResult((TestCustomResourceOutputData)null!); 18 | } 19 | 20 | public virtual Task Delete(CustomResourceRequest request, CancellationToken cancellationToken) 21 | { 22 | return Task.FromResult((TestCustomResourceOutputData)null!); 23 | } 24 | 25 | public virtual void Validate(CustomResourceRequest request) 26 | { 27 | } 28 | 29 | public virtual bool RequiresReplacement(CustomResourceRequest request) 30 | { 31 | return false; 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /tests/Common/TestCustomResourceOutputData.cs: -------------------------------------------------------------------------------- 1 | using Lambdajection.CustomResource; 2 | 3 | namespace Lambdajection 4 | { 5 | public class TestCustomResourceOutputData : ICustomResourceOutputData 6 | { 7 | public virtual string Id { get; set; } = string.Empty; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /tests/Common/TestLambda.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading; 3 | using System.Threading.Tasks; 4 | 5 | using Lambdajection.Core; 6 | 7 | namespace Lambdajection 8 | { 9 | public class TestLambda : ILambda 10 | { 11 | public object Request { get; set; } = null!; 12 | 13 | public Action? HandleAction { get; set; } = null; 14 | 15 | public virtual Task Handle(TestLambdaMessage request, CancellationToken cancellationToken = default) 16 | { 17 | Request = request; 18 | HandleAction?.Invoke(); 19 | return Task.FromResult(null!); 20 | } 21 | 22 | public virtual void Validate(TestLambdaMessage request) 23 | { 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /tests/Common/TestLambdaMessage.cs: -------------------------------------------------------------------------------- 1 | namespace Lambdajection 2 | { 3 | public class TestLambdaMessage 4 | { 5 | public string? Id { get; set; } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /tests/Common/TestStartup.cs: -------------------------------------------------------------------------------- 1 | using Lambdajection.Core; 2 | 3 | using Microsoft.Extensions.Configuration; 4 | using Microsoft.Extensions.DependencyInjection; 5 | using Microsoft.Extensions.Logging; 6 | 7 | namespace Lambdajection 8 | { 9 | public class TestStartup : ILambdaStartup 10 | { 11 | public IConfiguration Configuration { get; set; } = null!; 12 | 13 | public IServiceCollection Services { get; private set; } = null!; 14 | 15 | public ILoggingBuilder LoggingBuilder { get; private set; } = null!; 16 | 17 | public void ConfigureServices(IServiceCollection services) 18 | { 19 | Services = services; 20 | } 21 | 22 | public void ConfigureLogging(ILoggingBuilder builder) 23 | { 24 | LoggingBuilder = builder; 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /tests/Common/TypeOmitter.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | 3 | using AutoFixture.Kernel; 4 | 5 | internal class TypeOmitter : ISpecimenBuilder 6 | { 7 | public object Create(object request, ISpecimenContext context) 8 | { 9 | return request switch 10 | { 11 | PropertyInfo propInfo => propInfo.PropertyType == typeof(TType) ? new OmitSpecimen() : new NoSpecimen(), 12 | TypeInfo typeInfo => typeInfo.AsType() == typeof(TType) ? new OmitSpecimen() : new NoSpecimen(), 13 | _ => new NoSpecimen(), 14 | }; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /tests/Compilation/Projects/AmazonFactories/AmazonFactories.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | net7.0 4 | false 5 | CS8019 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /tests/Compilation/Projects/AmazonFactories/Handler.cs: -------------------------------------------------------------------------------- 1 | using System.Threading; 2 | using System.Threading.Tasks; 3 | 4 | using Amazon.Lambda.Core; 5 | 6 | using Amazon.S3; 7 | 8 | using Lambdajection.Attributes; 9 | using Lambdajection.Core; 10 | 11 | using Microsoft.Extensions.Configuration; 12 | using Microsoft.Extensions.DependencyInjection; 13 | 14 | namespace Lambdajection.CompilationTests.AmazonFactories 15 | { 16 | [Lambda(typeof(Startup))] 17 | public partial class Handler 18 | { 19 | private readonly S3Utility utility; 20 | 21 | public Handler(S3Utility utility) 22 | { 23 | this.utility = utility; 24 | } 25 | 26 | public Task Handle(string request, CancellationToken cancellationToken = default) 27 | { 28 | return Task.FromResult("ok"); 29 | } 30 | } 31 | } 32 | 33 | -------------------------------------------------------------------------------- /tests/Compilation/Projects/AmazonFactories/S3Utility.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | 3 | using Amazon.Lambda.Core; 4 | 5 | using Amazon.S3; 6 | 7 | using Lambdajection.Attributes; 8 | using Lambdajection.Core; 9 | 10 | using Microsoft.Extensions.Configuration; 11 | using Microsoft.Extensions.DependencyInjection; 12 | 13 | namespace Lambdajection.CompilationTests.AmazonFactories 14 | { 15 | public class S3Utility 16 | { 17 | public IAwsFactory Factory { get; set; } 18 | 19 | public S3Utility(IAwsFactory s3Factory) 20 | { 21 | this.Factory = s3Factory; 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /tests/Compilation/Projects/AmazonFactories/Startup.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | 3 | using Amazon.Lambda.Core; 4 | 5 | using Amazon.S3; 6 | 7 | using Lambdajection.Attributes; 8 | using Lambdajection.Core; 9 | 10 | using Microsoft.Extensions.Configuration; 11 | using Microsoft.Extensions.DependencyInjection; 12 | 13 | namespace Lambdajection.CompilationTests.AmazonFactories 14 | { 15 | public class Startup : ILambdaStartup 16 | { 17 | public IConfiguration Configuration { get; } 18 | 19 | public Startup(IConfiguration configuration) 20 | { 21 | this.Configuration = configuration; 22 | } 23 | 24 | public void ConfigureServices(IServiceCollection services) 25 | { 26 | services.UseAwsService(); 27 | services.AddSingleton(); 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /tests/Compilation/Projects/ConfigFactory/ConfigFactory.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | net7.0 4 | false 5 | CS8019 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /tests/Compilation/Projects/ConfigFactory/Handler.cs: -------------------------------------------------------------------------------- 1 | using System.Threading; 2 | using System.Threading.Tasks; 3 | 4 | using Amazon.Lambda.Core; 5 | 6 | using Lambdajection.Attributes; 7 | using Lambdajection.Core; 8 | 9 | using Microsoft.Extensions.Configuration; 10 | using Microsoft.Extensions.DependencyInjection; 11 | 12 | namespace Lambdajection.CompilationTests.ConfigFactory 13 | { 14 | [Lambda(typeof(Startup), ConfigFactory = typeof(JsonConfigFactory))] 15 | public partial class Handler 16 | { 17 | private readonly IConfiguration config; 18 | 19 | public Handler(IConfiguration config) 20 | { 21 | this.config = config; 22 | } 23 | 24 | public Task Handle(string _, CancellationToken cancellationToken = default) 25 | { 26 | var value = config.GetValue("TestKey"); 27 | return Task.FromResult(value); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /tests/Compilation/Projects/ConfigFactory/JsonConfigFactory.cs: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | using System.Threading.Tasks; 3 | 4 | using Amazon.Lambda.Core; 5 | 6 | using Lambdajection.Attributes; 7 | using Lambdajection.Core; 8 | 9 | using Microsoft.Extensions.Configuration; 10 | using Microsoft.Extensions.DependencyInjection; 11 | 12 | namespace Lambdajection.CompilationTests.ConfigFactory 13 | { 14 | public class JsonConfigFactory : ILambdaConfigFactory 15 | { 16 | public IConfigurationRoot Create() 17 | { 18 | return new ConfigurationBuilder() 19 | // when this is loaded into the test assembly, the CWD will be the tests folder 20 | .SetBasePath(Directory.GetCurrentDirectory() + "/Compilation/Projects/ConfigFactory/") 21 | .AddJsonFile("appsettings.json", optional: true) 22 | .Build(); 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /tests/Compilation/Projects/ConfigFactory/Startup.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | 3 | using Amazon.Lambda.Core; 4 | 5 | using Lambdajection.Attributes; 6 | using Lambdajection.Core; 7 | 8 | using Microsoft.Extensions.Configuration; 9 | using Microsoft.Extensions.DependencyInjection; 10 | 11 | namespace Lambdajection.CompilationTests.ConfigFactory 12 | { 13 | public class Startup : ILambdaStartup 14 | { 15 | public void ConfigureServices(IServiceCollection services) 16 | { 17 | // do nothing 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /tests/Compilation/Projects/ConfigFactory/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "TestKey": "TestValue" 3 | } -------------------------------------------------------------------------------- /tests/Compilation/Projects/Configuration/Configuration.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | net7.0 4 | false 5 | CS8019 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /tests/Compilation/Projects/Configuration/Handler.cs: -------------------------------------------------------------------------------- 1 | using System.Threading; 2 | using System.Threading.Tasks; 3 | 4 | using Amazon.Lambda.Core; 5 | 6 | using Lambdajection.Attributes; 7 | using Lambdajection.Core; 8 | 9 | using Microsoft.Extensions.Configuration; 10 | using Microsoft.Extensions.DependencyInjection; 11 | using Microsoft.Extensions.Options; 12 | 13 | namespace Lambdajection.CompilationTests.Configuration 14 | { 15 | [Lambda(typeof(Startup))] 16 | public partial class Handler 17 | { 18 | private readonly Options exampleOptions; 19 | 20 | public Handler(IOptions exampleOptions) 21 | { 22 | this.exampleOptions = exampleOptions.Value; 23 | } 24 | 25 | public Task Handle(string request, CancellationToken cancellationToken = default) 26 | { 27 | return Task.FromResult(exampleOptions); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /tests/Compilation/Projects/Configuration/Options.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | 3 | using Amazon.Lambda.Core; 4 | 5 | using Lambdajection.Attributes; 6 | using Lambdajection.Core; 7 | using Lambdajection.Encryption; 8 | 9 | using Microsoft.Extensions.Configuration; 10 | using Microsoft.Extensions.DependencyInjection; 11 | 12 | namespace Lambdajection.CompilationTests.Configuration 13 | { 14 | 15 | [LambdaOptions(typeof(Handler), "Example")] 16 | public class Options 17 | { 18 | public string ExampleConfigValue { get; set; } = ""; 19 | 20 | [Encrypted] 21 | public string ExampleEncryptedValue { get; set; } = ""; 22 | } 23 | } -------------------------------------------------------------------------------- /tests/Compilation/Projects/Configuration/Startup.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | 3 | using Amazon.Lambda.Core; 4 | 5 | using Lambdajection.Attributes; 6 | using Lambdajection.Core; 7 | using Lambdajection.Encryption; 8 | 9 | using Microsoft.Extensions.Configuration; 10 | using Microsoft.Extensions.DependencyInjection; 11 | 12 | using NSubstitute; 13 | 14 | namespace Lambdajection.CompilationTests.Configuration 15 | { 16 | public class Startup : ILambdaStartup 17 | { 18 | public static IDecryptionService DecryptionService { get; } = Substitute.For(); 19 | 20 | public IConfiguration Configuration { get; } 21 | 22 | public Startup(IConfiguration configuration) 23 | { 24 | this.Configuration = configuration; 25 | } 26 | 27 | public void ConfigureServices(IServiceCollection services) 28 | { 29 | DecryptionService.Decrypt(Arg.Any()).Returns(x => "[decrypted] " + x.ArgAt(0)); 30 | 31 | services.AddSingleton(DecryptionService); 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /tests/Compilation/Projects/CustomResources/CustomResources.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | net7.0 4 | false 5 | CS8019 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /tests/Compilation/Projects/CustomResources/Metadata.cs: -------------------------------------------------------------------------------- 1 | using Lambdajection.Attributes; 2 | 3 | namespace Lambdajection.CompilationTests.CustomResources 4 | { 5 | public class Metadata 6 | { 7 | [UpdateRequiresReplacement] 8 | public string CreatedBy { get; set; } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /tests/Compilation/Projects/CustomResources/ResourceProperties.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.ComponentModel.DataAnnotations; 3 | 4 | using Lambdajection.Attributes; 5 | 6 | namespace Lambdajection.CompilationTests.CustomResources 7 | { 8 | public class ResourceProperties 9 | { 10 | [MinLength(3, ErrorMessage = "Expected Error Message")] 11 | public string Name { get; set; } 12 | 13 | public bool ShouldFail { get; set; } = false; 14 | 15 | // This is a test - the validations generator should not recurse into collection types 16 | // (it will cause a stack overflow if it does recurse, so simply running it will suffice) 17 | public List ValidationsGeneratorShouldNotRecurseIntoCollections { get; set; } 18 | 19 | public string ErrorMessage { get; set; } = string.Empty; 20 | 21 | [UpdateRequiresReplacement] 22 | public ulong Serial { get; set; } = 0UL; 23 | 24 | public Metadata Metadata { get; set; } = new Metadata(); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /tests/Compilation/Projects/CustomResources/ResponseData.cs: -------------------------------------------------------------------------------- 1 | using Lambdajection.CustomResource; 2 | 3 | namespace Lambdajection.CompilationTests.CustomResources 4 | { 5 | public class ResponseData : ICustomResourceOutputData 6 | { 7 | public string Id { get; set; } 8 | 9 | public string MethodCalled { get; set; } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /tests/Compilation/Projects/CustomResources/Startup.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | 3 | using Amazon.Lambda.Core; 4 | 5 | using Lambdajection.Attributes; 6 | using Lambdajection.Core; 7 | 8 | using Microsoft.Extensions.Configuration; 9 | using Microsoft.Extensions.DependencyInjection; 10 | 11 | namespace Lambdajection.CompilationTests.CustomResources 12 | { 13 | public class Startup : ILambdaStartup 14 | { 15 | public void ConfigureServices(IServiceCollection services) 16 | { 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /tests/Compilation/Projects/CustomRunnerMethod/CustomRunnerMethod.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | net7.0 4 | linux-x64 5 | false 6 | false 7 | CS8019 8 | 9 | 10 | 11 | 12 | 13 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /tests/Compilation/Projects/CustomRunnerMethod/Handler.cs: -------------------------------------------------------------------------------- 1 | using System.Threading; 2 | using System.Threading.Tasks; 3 | 4 | using Amazon.Lambda.Core; 5 | 6 | using Lambdajection.Attributes; 7 | using Lambdajection.Core; 8 | 9 | using Microsoft.Extensions.Configuration; 10 | using Microsoft.Extensions.DependencyInjection; 11 | 12 | namespace Lambdajection.CompilationTests.CustomRunnerMethod 13 | { 14 | [Lambda(typeof(Startup), RunnerMethod = "Process")] 15 | public partial class Handler 16 | { 17 | public Task Handle(string request, CancellationToken cancellationToken = default) 18 | { 19 | return Task.FromResult("Success"); 20 | } 21 | } 22 | } 23 | 24 | -------------------------------------------------------------------------------- /tests/Compilation/Projects/CustomRunnerMethod/Startup.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | 3 | using Amazon.Lambda.Core; 4 | 5 | using Lambdajection.Attributes; 6 | using Lambdajection.Core; 7 | 8 | using Microsoft.Extensions.Configuration; 9 | using Microsoft.Extensions.DependencyInjection; 10 | 11 | namespace Lambdajection.CompilationTests.CustomRunnerMethod 12 | { 13 | public class Startup : ILambdaStartup 14 | { 15 | public void ConfigureServices(IServiceCollection services) 16 | { 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /tests/Compilation/Projects/Directory.Build.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | true 4 | Debug 5 | PackageReference 6 | 7 | 8 | 9 | <_BasePath>$(MSBuildThisFileDirectory)../../../ 10 | $(_BasePath).nuget/tests 11 | $(_BasePath)bin/CompilationTestProjects/$(MSBuildProjectName)/$(Configuration) 12 | $(_BasePath)obj/CompilationTestProjects/$(MSBuildProjectName) 13 | $(_BasePath)obj/CompilationTestProjects/$(MSBuildProjectName)/$(Configuration) 14 | $(_BasePath)bin/Packages/$(Configuration) 15 | 16 | $(RestoreLocation); 17 | $(RestoreAdditionalProjectSources) 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /tests/Compilation/Projects/Disposables/AsyncDisposableHandler.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading; 3 | using System.Threading.Tasks; 4 | 5 | using Amazon.Lambda.Core; 6 | 7 | using Lambdajection.Attributes; 8 | using Lambdajection.Core; 9 | 10 | using Microsoft.Extensions.Configuration; 11 | using Microsoft.Extensions.DependencyInjection; 12 | using Microsoft.Extensions.Options; 13 | 14 | namespace Lambdajection.CompilationTests.Disposables 15 | { 16 | [Lambda(typeof(Startup))] 17 | public partial class AsyncDisposableHandler : IAsyncDisposable 18 | { 19 | public static bool DisposeAsyncWasCalled { get; set; } = false; 20 | 21 | public Task Handle(string request, CancellationToken cancellationToken = default) 22 | { 23 | return Task.FromResult("ok"); 24 | } 25 | 26 | public ValueTask DisposeAsync() 27 | { 28 | DisposeAsyncWasCalled = true; 29 | 30 | #pragma warning disable CA1816 31 | GC.SuppressFinalize(this); 32 | #pragma warning restore CA1816 33 | 34 | return new ValueTask(); 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /tests/Compilation/Projects/Disposables/DisposableHandler.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading; 3 | using System.Threading.Tasks; 4 | 5 | using Amazon.Lambda.Core; 6 | 7 | using Lambdajection.Attributes; 8 | using Lambdajection.Core; 9 | 10 | using Microsoft.Extensions.Configuration; 11 | using Microsoft.Extensions.DependencyInjection; 12 | using Microsoft.Extensions.Options; 13 | 14 | namespace Lambdajection.CompilationTests.Disposables 15 | { 16 | [Lambda(typeof(Startup))] 17 | public partial class DisposableHandler : IDisposable 18 | { 19 | public static bool DisposeWasCalled { get; set; } = false; 20 | 21 | public Task Handle(string request, CancellationToken cancellationToken = default) 22 | { 23 | return Task.FromResult("ok"); 24 | } 25 | 26 | public void Dispose() 27 | { 28 | DisposeWasCalled = true; 29 | GC.SuppressFinalize(this); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /tests/Compilation/Projects/Disposables/Disposables.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | net7.0 4 | false 5 | CS8019 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /tests/Compilation/Projects/Disposables/Startup.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | 3 | using Amazon.Lambda.Core; 4 | 5 | using Lambdajection.Attributes; 6 | using Lambdajection.Core; 7 | 8 | using Microsoft.Extensions.Configuration; 9 | using Microsoft.Extensions.DependencyInjection; 10 | 11 | 12 | namespace Lambdajection.CompilationTests.Disposables 13 | { 14 | public class Startup : ILambdaStartup 15 | { 16 | public void ConfigureServices(IServiceCollection services) 17 | { 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /tests/Compilation/Projects/IamPermissions/Handler.cs: -------------------------------------------------------------------------------- 1 | using System.Threading; 2 | using System.Threading.Tasks; 3 | 4 | using Amazon.Lambda.Core; 5 | 6 | using Lambdajection.Attributes; 7 | using Lambdajection.Core; 8 | 9 | using Microsoft.Extensions.Configuration; 10 | using Microsoft.Extensions.DependencyInjection; 11 | 12 | namespace Lambdajection.CompilationTests.IamPermissions 13 | { 14 | [Lambda(typeof(Startup))] 15 | public partial class Handler 16 | { 17 | private readonly Utility utility; 18 | 19 | public Handler(Utility utility) 20 | { 21 | this.utility = utility; 22 | } 23 | 24 | public async Task Handle(string request, CancellationToken cancellationToken = default) 25 | { 26 | utility.ArbitraryOperation(); 27 | await utility.GetObject(); 28 | return (string)null!; 29 | } 30 | } 31 | } 32 | 33 | -------------------------------------------------------------------------------- /tests/Compilation/Projects/IamPermissions/IamPermissions.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | net7.0 4 | false 5 | CS8019 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /tests/Compilation/Projects/IamPermissions/Startup.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | 3 | using Amazon.Lambda.Core; 4 | using Amazon.S3; 5 | 6 | using Lambdajection.Attributes; 7 | using Lambdajection.Core; 8 | 9 | using Microsoft.Extensions.Configuration; 10 | using Microsoft.Extensions.DependencyInjection; 11 | 12 | using NSubstitute; 13 | 14 | namespace Lambdajection.CompilationTests.IamPermissions 15 | { 16 | public class Startup : ILambdaStartup 17 | { 18 | public IConfiguration Configuration { get; } 19 | 20 | public Startup(IConfiguration configuration) 21 | { 22 | this.Configuration = configuration; 23 | } 24 | 25 | public void ConfigureServices(IServiceCollection services) 26 | { 27 | services.AddSingleton(); 28 | 29 | var s3Substitute = Substitute.For(); 30 | services.AddSingleton(s3Substitute); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /tests/Compilation/Projects/IamPermissions/Utility.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | 3 | using Amazon.Lambda.Core; 4 | using Amazon.S3; 5 | 6 | using Lambdajection.Attributes; 7 | using Lambdajection.Core; 8 | using Lambdajection.Framework; 9 | 10 | using Microsoft.Extensions.Configuration; 11 | using Microsoft.Extensions.DependencyInjection; 12 | 13 | namespace Lambdajection.CompilationTests.IamPermissions 14 | { 15 | public class Utility 16 | { 17 | private readonly IAmazonS3 s3Client; 18 | 19 | public Utility( 20 | IAmazonS3 s3Client 21 | ) 22 | { 23 | this.s3Client = s3Client; 24 | } 25 | 26 | [RequiresIamPermission("ec2:ArbitraryOperation1")] 27 | [RequiresIamPermission("ec2:ArbitraryOperation2")] 28 | public void ArbitraryOperation() 29 | { 30 | } 31 | 32 | public async Task GetObject() 33 | { 34 | await s3Client.GetObjectAsync("test", "test"); 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /tests/Compilation/Projects/LambdaContext/Handler.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading; 3 | using System.Threading.Tasks; 4 | 5 | using Amazon.Lambda.Core; 6 | 7 | using Lambdajection.Attributes; 8 | using Lambdajection.Core; 9 | 10 | using Microsoft.Extensions.Configuration; 11 | using Microsoft.Extensions.DependencyInjection; 12 | 13 | namespace Lambdajection.CompilationTests.LambdaContext 14 | { 15 | [Lambda(typeof(Startup))] 16 | public partial class Handler 17 | { 18 | private readonly ILambdaContext context; 19 | 20 | public Handler(ILambdaContext context) 21 | { 22 | Console.WriteLine("Testing LambdaContext"); 23 | this.context = context; 24 | } 25 | 26 | public Task Handle(string request, CancellationToken cancellationToken = default) 27 | { 28 | return Task.FromResult(context.AwsRequestId); 29 | } 30 | } 31 | } 32 | 33 | -------------------------------------------------------------------------------- /tests/Compilation/Projects/LambdaContext/LambdaContext.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | net7.0 4 | false 5 | CS8019 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /tests/Compilation/Projects/LambdaContext/Startup.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | 3 | using Amazon.Lambda.Core; 4 | 5 | using Lambdajection.Attributes; 6 | using Lambdajection.Core; 7 | 8 | using Microsoft.Extensions.Configuration; 9 | using Microsoft.Extensions.DependencyInjection; 10 | 11 | namespace Lambdajection.CompilationTests.LambdaContext 12 | { 13 | public class Startup : ILambdaStartup 14 | { 15 | public void ConfigureServices(IServiceCollection services) 16 | { 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /tests/Compilation/Projects/MissingLambdaInterface/Handler.cs: -------------------------------------------------------------------------------- 1 | using System.Threading; 2 | using System.Threading.Tasks; 3 | 4 | using Lambdajection.Attributes; 5 | using Lambdajection.Core; 6 | 7 | using Microsoft.Extensions.Configuration; 8 | using Microsoft.Extensions.DependencyInjection; 9 | 10 | namespace Lambdajection.CompilationTests.MissingLambdaInterface 11 | { 12 | [MissingLambdaInterface(typeof(Startup))] 13 | public partial class Handler 14 | { 15 | public Handler() 16 | { 17 | } 18 | 19 | public Task Handle(string request, CancellationToken cancellationToken = default) 20 | { 21 | return Task.FromResult(request); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /tests/Compilation/Projects/MissingLambdaInterface/MissingLambdaInterface.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | net7.0 4 | false 5 | CS8019 6 | Lambdajection.CompilationTests.MissingLambdaInterface 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /tests/Compilation/Projects/MissingLambdaInterface/MissingLambdaInterfaceAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | 4 | using Lambdajection.Attributes; 5 | using Lambdajection.Framework; 6 | 7 | namespace Lambdajection.CompilationTests.MissingLambdaInterface 8 | { 9 | [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)] 10 | [Conditional("CodeGeneration")] 11 | [LambdaHost("Lambdajection.Core", "DefaultLambdaHost")] 12 | [LambdaInterface("Lambdajection.Core", "NonExistentInterface")] 13 | public class MissingLambdaInterfaceAttribute : LambdaAttribute 14 | { 15 | public MissingLambdaInterfaceAttribute(Type startup) 16 | : base(startup) 17 | { 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /tests/Compilation/Projects/MissingLambdaInterface/Startup.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | 3 | using Lambdajection.Attributes; 4 | using Lambdajection.Core; 5 | 6 | using Microsoft.Extensions.Configuration; 7 | using Microsoft.Extensions.DependencyInjection; 8 | 9 | namespace Lambdajection.CompilationTests.MissingLambdaInterface 10 | { 11 | public class Startup : ILambdaStartup 12 | { 13 | public void ConfigureServices(IServiceCollection services) 14 | { 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /tests/Compilation/Projects/NoHandleMethod/Handler.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | 3 | using Amazon.Lambda.Core; 4 | 5 | using Lambdajection.Attributes; 6 | using Lambdajection.Core; 7 | 8 | using Microsoft.Extensions.Configuration; 9 | using Microsoft.Extensions.DependencyInjection; 10 | using Microsoft.Extensions.Options; 11 | 12 | namespace Lambdajection.CompilationTests.NoHandleMethod 13 | { 14 | [Lambda(typeof(Startup))] 15 | public partial class Handler 16 | { 17 | private readonly Options exampleOptions; 18 | 19 | public Handler(IOptions exampleOptions) 20 | { 21 | this.exampleOptions = exampleOptions.Value; 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /tests/Compilation/Projects/NoHandleMethod/NoHandleMethod.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | net7.0 4 | false 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /tests/Compilation/Projects/NoHandleMethod/Startup.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | 3 | using Amazon.Lambda.Core; 4 | 5 | using Lambdajection.Attributes; 6 | using Lambdajection.Core; 7 | 8 | using Microsoft.Extensions.Configuration; 9 | using Microsoft.Extensions.DependencyInjection; 10 | 11 | 12 | namespace Lambdajection.CompilationTests.NoHandleMethod 13 | { 14 | public class Startup : ILambdaStartup 15 | { 16 | public void ConfigureServices(IServiceCollection services) 17 | { 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /tests/Compilation/Projects/Permissionless/Handler.cs: -------------------------------------------------------------------------------- 1 | using System.Threading; 2 | using System.Threading.Tasks; 3 | 4 | using Amazon.Lambda.Core; 5 | 6 | using Lambdajection.Attributes; 7 | using Lambdajection.Core; 8 | 9 | using Microsoft.Extensions.Configuration; 10 | using Microsoft.Extensions.DependencyInjection; 11 | 12 | namespace Lambdajection.CompilationTests.Permissionless 13 | { 14 | [Lambda(typeof(Startup))] 15 | public partial class Handler 16 | { 17 | public Task Handle(string request, CancellationToken cancellationToken = default) 18 | { 19 | return Task.FromResult(string.Empty); 20 | } 21 | } 22 | } 23 | 24 | -------------------------------------------------------------------------------- /tests/Compilation/Projects/Permissionless/Permissionless.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | net7.0 4 | false 5 | CS8019 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /tests/Compilation/Projects/Permissionless/Startup.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | 3 | using Amazon.Lambda.Core; 4 | 5 | using Lambdajection.Attributes; 6 | using Lambdajection.Core; 7 | 8 | using Microsoft.Extensions.Configuration; 9 | using Microsoft.Extensions.DependencyInjection; 10 | 11 | using NSubstitute; 12 | 13 | namespace Lambdajection.CompilationTests.Permissionless 14 | { 15 | public class Startup : ILambdaStartup 16 | { 17 | public IConfiguration Configuration { get; } 18 | 19 | public Startup(IConfiguration configuration) 20 | { 21 | this.Configuration = configuration; 22 | } 23 | 24 | public void ConfigureServices(IServiceCollection services) 25 | { 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /tests/Compilation/Projects/Serialization/Handler.cs: -------------------------------------------------------------------------------- 1 | using System.Threading; 2 | using System.Threading.Tasks; 3 | 4 | using Amazon.Lambda.Core; 5 | 6 | using Lambdajection.Attributes; 7 | using Lambdajection.Core; 8 | 9 | using Microsoft.Extensions.Configuration; 10 | using Microsoft.Extensions.DependencyInjection; 11 | 12 | namespace Lambdajection.CompilationTests.Serialization 13 | { 14 | [Lambda(typeof(Startup))] 15 | public partial class Handler 16 | { 17 | public Task Handle(Request request, CancellationToken cancellationToken = default) 18 | { 19 | return Task.FromResult(request.Id); 20 | } 21 | } 22 | } 23 | 24 | -------------------------------------------------------------------------------- /tests/Compilation/Projects/Serialization/Request.cs: -------------------------------------------------------------------------------- 1 | namespace Lambdajection.CompilationTests.Serialization 2 | { 3 | public class Request 4 | { 5 | public string? Id { get; set; } = string.Empty; 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /tests/Compilation/Projects/Serialization/Serialization.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | net7.0 4 | false 5 | CS8019 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /tests/Compilation/Projects/Serialization/Startup.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json; 2 | using System.Threading.Tasks; 3 | 4 | using Amazon.Lambda.Core; 5 | 6 | using Lambdajection.Attributes; 7 | using Lambdajection.Core; 8 | 9 | using Microsoft.Extensions.Configuration; 10 | using Microsoft.Extensions.DependencyInjection; 11 | 12 | namespace Lambdajection.CompilationTests.Serialization 13 | { 14 | public class Startup : ILambdaStartup 15 | { 16 | public void ConfigureServices(IServiceCollection services) 17 | { 18 | services.AddSingleton(new JsonSerializerOptions 19 | { 20 | PropertyNamingPolicy = JsonNamingPolicy.CamelCase, 21 | }); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /tests/Compilation/Projects/Sns/Handler.cs: -------------------------------------------------------------------------------- 1 | using System.Threading; 2 | using System.Threading.Tasks; 3 | 4 | using Amazon.Lambda.Core; 5 | 6 | using Lambdajection.Attributes; 7 | using Lambdajection.Core; 8 | using Lambdajection.Sns; 9 | 10 | using Microsoft.Extensions.Configuration; 11 | using Microsoft.Extensions.DependencyInjection; 12 | 13 | namespace Lambdajection.CompilationTests.Sns 14 | { 15 | [SnsEventHandler(typeof(Startup))] 16 | public partial class Handler 17 | { 18 | public Task Handle(SnsMessage request, CancellationToken cancellationToken = default) 19 | { 20 | return Task.FromResult(request.Message.StackId); 21 | } 22 | } 23 | } 24 | 25 | -------------------------------------------------------------------------------- /tests/Compilation/Projects/Sns/Sns.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | net7.0 4 | false 5 | CS8019 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /tests/Compilation/Projects/Sns/Startup.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json; 2 | using System.Threading.Tasks; 3 | 4 | using Amazon.Lambda.Core; 5 | 6 | using Lambdajection.Attributes; 7 | using Lambdajection.Core; 8 | 9 | using Microsoft.Extensions.Configuration; 10 | using Microsoft.Extensions.DependencyInjection; 11 | 12 | namespace Lambdajection.CompilationTests.Sns 13 | { 14 | public class Startup : ILambdaStartup 15 | { 16 | public void ConfigureServices(IServiceCollection services) 17 | { 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /tests/Compilation/Projects/Tracing/ConcreteAmazonClient.cs: -------------------------------------------------------------------------------- 1 | using Amazon.Runtime; 2 | using Amazon.Runtime.Internal.Auth; 3 | using Amazon.XRay.Recorder.Handlers.AwsSdk.Internal; 4 | 5 | namespace Lambdajection.CompilationTests.Tracing 6 | { 7 | public class ConcreteAmazonClient : AmazonServiceClient 8 | { 9 | public ConcreteAmazonClient() : base(new AnonymousAWSCredentials(), new ConcreteClientConfig()) 10 | { 11 | } 12 | 13 | protected override AbstractAWSSigner CreateSigner() 14 | { 15 | return null!; 16 | } 17 | 18 | public bool IsTracingEnabled() 19 | { 20 | var current = this.RuntimePipeline.Handler; 21 | 22 | while (current != null) 23 | { 24 | if (current.GetType() == typeof(XRayPipelineHandler)) 25 | { 26 | return true; 27 | } 28 | 29 | current = current.InnerHandler; 30 | } 31 | 32 | return false; 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /tests/Compilation/Projects/Tracing/ConcreteClientConfig.cs: -------------------------------------------------------------------------------- 1 | using Amazon.Runtime; 2 | 3 | namespace Lambdajection.CompilationTests.Tracing 4 | { 5 | public class ConcreteClientConfig : ClientConfig 6 | { 7 | public override void Validate() 8 | { 9 | } 10 | 11 | public override string UserAgent => string.Empty; 12 | 13 | public override string ServiceVersion => string.Empty; 14 | 15 | public override string RegionEndpointServiceName => "concrete"; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /tests/Compilation/Projects/Tracing/Handler.cs: -------------------------------------------------------------------------------- 1 | using System.Threading; 2 | using System.Threading.Tasks; 3 | 4 | using Amazon.Lambda.Core; 5 | using Amazon.XRay.Recorder.Core; 6 | 7 | using Lambdajection.Attributes; 8 | using Lambdajection.Core; 9 | 10 | namespace Lambdajection.CompilationTests.Tracing 11 | { 12 | [Lambda(typeof(Startup))] 13 | public partial class Handler 14 | { 15 | private readonly IAWSXRayRecorder recorder; 16 | 17 | public Handler( 18 | IAWSXRayRecorder recorder 19 | ) 20 | { 21 | this.recorder = recorder; 22 | } 23 | 24 | public Task Handle(string request, CancellationToken cancellationToken = default) 25 | { 26 | var client = new ConcreteAmazonClient(); 27 | return Task.FromResult(client.IsTracingEnabled()); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /tests/Compilation/Projects/Tracing/Startup.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | 3 | using Amazon.Lambda.Core; 4 | 5 | using Lambdajection.Core; 6 | 7 | using Microsoft.Extensions.Configuration; 8 | using Microsoft.Extensions.DependencyInjection; 9 | 10 | namespace Lambdajection.CompilationTests.Tracing 11 | { 12 | public class Startup : ILambdaStartup 13 | { 14 | public void ConfigureServices(IServiceCollection services) 15 | { 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /tests/Compilation/Projects/Tracing/Tracing.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | net7.0 4 | false 5 | CS8019 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /tests/Compilation/Tests/ConfigFactoryTests.cs: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | using System.Text.Json; 3 | using System.Threading.Tasks; 4 | 5 | using FluentAssertions; 6 | 7 | using Microsoft.CodeAnalysis; 8 | using Microsoft.CodeAnalysis.MSBuild; 9 | 10 | using NUnit.Framework; 11 | 12 | #pragma warning disable SA1009 13 | namespace Lambdajection.Tests.Compilation 14 | { 15 | [Category("Integration")] 16 | public class ConfigFactoryTests 17 | { 18 | private const string projectPath = "Compilation/Projects/ConfigFactory/ConfigFactory.csproj"; 19 | 20 | private static Project project = null!; 21 | 22 | [OneTimeSetUp] 23 | public async Task Setup() 24 | { 25 | project = await MSBuildProjectExtensions.LoadProject(projectPath); 26 | } 27 | 28 | [Test, Auto] 29 | public async Task Handler_RunsWithoutError() 30 | { 31 | using var generation = await project.GenerateAssembly(); 32 | var (assembly, _) = generation; 33 | var handlerType = assembly.GetType("Lambdajection.CompilationTests.ConfigFactory.Handler")!; 34 | var runMethod = handlerType.GetMethod("Run")!; 35 | 36 | var inputStream = await StreamUtils.CreateJsonStream(string.Empty); 37 | var resultStream = await (Task)runMethod.Invoke(null, new[] { inputStream, null })!; 38 | var result = await JsonSerializer.DeserializeAsync(resultStream); 39 | 40 | result.Should().Be("TestValue"); 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /tests/Compilation/Tests/CustomRunnerMethodTests.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | 3 | using FluentAssertions; 4 | 5 | using Microsoft.CodeAnalysis; 6 | using Microsoft.CodeAnalysis.MSBuild; 7 | 8 | using NUnit.Framework; 9 | 10 | #pragma warning disable SA1009 11 | namespace Lambdajection.Tests.Compilation 12 | { 13 | [Category("Integration")] 14 | public class CustomRunnerMethodTests 15 | { 16 | private const string projectPath = "Compilation/Projects/CustomRunnerMethod/CustomRunnerMethod.csproj"; 17 | 18 | private static Project project = null!; 19 | 20 | [OneTimeSetUp] 21 | public async Task Setup() 22 | { 23 | project = await MSBuildProjectExtensions.LoadProject(projectPath); 24 | } 25 | 26 | [Test] 27 | public async Task Run_IsNotGenerated() 28 | { 29 | using var generation = await project.GenerateAssembly(); 30 | var (assembly, _) = generation; 31 | var handlerType = assembly.GetType("Lambdajection.CompilationTests.CustomRunnerMethod.Handler")!; 32 | var runMethod = handlerType.GetMethod("Run"); 33 | 34 | runMethod.Should().BeNull(); 35 | } 36 | 37 | [Test] 38 | public async Task Process_IsGenerated() 39 | { 40 | using var generation = await project.GenerateAssembly(); 41 | var (assembly, _) = generation; 42 | var handlerType = assembly.GetType("Lambdajection.CompilationTests.CustomRunnerMethod.Handler")!; 43 | var processMethod = handlerType.GetMethod("Process"); 44 | 45 | processMethod.Should().NotBeNull(); 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /tests/Compilation/Tests/LambdaContextTests.cs: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | using System.Text.Json; 3 | using System.Threading.Tasks; 4 | 5 | using Amazon.Lambda.Core; 6 | 7 | using FluentAssertions; 8 | 9 | using Microsoft.CodeAnalysis; 10 | using Microsoft.CodeAnalysis.MSBuild; 11 | 12 | using NUnit.Framework; 13 | 14 | #pragma warning disable SA1009 15 | namespace Lambdajection.Tests.Compilation 16 | { 17 | [Category("Integration")] 18 | public class LambdaContextTests 19 | { 20 | private const string projectPath = "Compilation/Projects/LambdaContext/LambdaContext.csproj"; 21 | 22 | private static Project project = null!; 23 | 24 | [OneTimeSetUp] 25 | public async Task Setup() 26 | { 27 | project = await MSBuildProjectExtensions.LoadProject(projectPath); 28 | } 29 | 30 | [Test, Auto] 31 | public async Task Run_ReturnsContext( 32 | ILambdaContext context 33 | ) 34 | { 35 | using var generation = await project.GenerateAssembly(); 36 | var (assembly, _) = generation; 37 | var handlerType = assembly.GetType("Lambdajection.CompilationTests.LambdaContext.Handler")!; 38 | var runMethod = handlerType.GetMethod("Run")!; 39 | 40 | using var inputStream = await StreamUtils.CreateJsonStream(string.Empty); 41 | var resultStream = await (Task)runMethod.Invoke(null, new object[] { inputStream, context })!; 42 | var result = await JsonSerializer.DeserializeAsync(resultStream); 43 | 44 | result.Should().Be(context.AwsRequestId); 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /tests/Compilation/Tests/MissingLambdaInterfaceTests.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | 3 | using FluentAssertions; 4 | 5 | using Microsoft.CodeAnalysis; 6 | using Microsoft.CodeAnalysis.MSBuild; 7 | 8 | using NUnit.Framework; 9 | 10 | #pragma warning disable SA1009 11 | namespace Lambdajection.Tests.Compilation 12 | { 13 | [Category("Integration")] 14 | public class MissingLambdaInterfaceTests 15 | { 16 | private const string projectPath = "Compilation/Projects/MissingLambdaInterface/MissingLambdaInterface.csproj"; 17 | 18 | private static Project project = null!; 19 | 20 | [OneTimeSetUp] 21 | public async Task Setup() 22 | { 23 | project = await MSBuildProjectExtensions.LoadProject(projectPath); 24 | } 25 | 26 | [Test] 27 | public async Task ShouldFailCompilationWithLJ0003() 28 | { 29 | var diagnostics = await project.GetGeneratorDiagnostics(); 30 | diagnostics.Should().Contain(diagnostic => diagnostic.Id == "LJ0003"); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /tests/Compilation/Tests/NoHandleMethodTests.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | 3 | using FluentAssertions; 4 | 5 | using Microsoft.CodeAnalysis; 6 | using Microsoft.CodeAnalysis.MSBuild; 7 | 8 | using NUnit.Framework; 9 | 10 | namespace Lambdajection.Tests.Compilation 11 | { 12 | [Category("Integration")] 13 | public class NoHandleMethodTests 14 | { 15 | private const string projectPath = "Compilation/Projects/NoHandleMethod/NoHandleMethod.csproj"; 16 | 17 | private static Project project = null!; 18 | 19 | [OneTimeSetUp] 20 | public async Task Setup() 21 | { 22 | project = await MSBuildProjectExtensions.LoadProject(projectPath); 23 | } 24 | 25 | [Test, Auto] 26 | public async Task CompilationFails_WithLJ0001() 27 | { 28 | var diagnostics = await project.GetGeneratorDiagnostics(); 29 | diagnostics.Should().Contain(diagnostic => diagnostic.Id == "LJ0001"); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /tests/Compilation/Tests/Setup.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics; 2 | using System.IO; 3 | 4 | using NUnit.Framework; 5 | 6 | using static System.Environment; 7 | 8 | namespace Lambdajection.Tests.Compilation 9 | { 10 | [SetUpFixture] 11 | [Category("Integration")] 12 | public class Setup 13 | { 14 | [OneTimeSetUp] 15 | public void RestoreCompilationProjects() 16 | { 17 | Directory.SetCurrentDirectory(TestMetadata.TestDirectory); 18 | 19 | using var restoreProcess = Process.Start("dotnet", $"restore Compilation/Projects/compilation-projects.sln -p:LambdajectionVersion={TestMetadata.PackageVersion} -t:Restore -nodereuse:false"); 20 | restoreProcess.WaitForExit(); 21 | 22 | if (restoreProcess.ExitCode != 0) 23 | { 24 | Exit(restoreProcess.ExitCode); 25 | } 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /tests/Compilation/Utils/HandlerWrapper.cs: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | using System.Reflection; 3 | using System.Text.Json; 4 | using System.Threading.Tasks; 5 | 6 | namespace Lambdajection 7 | { 8 | public class HandlerWrapper 9 | { 10 | private readonly Assembly assembly; 11 | private readonly string typeName; 12 | 13 | public HandlerWrapper(Assembly assembly, string typeName) 14 | { 15 | this.assembly = assembly; 16 | this.typeName = typeName; 17 | } 18 | 19 | public async Task Run(params object[] args) 20 | { 21 | var type = assembly.GetType(typeName)!; 22 | var runMethod = type.GetMethod("Run")!; 23 | 24 | var resultStream = await (Task)runMethod.Invoke(null, args)!; 25 | return await JsonSerializer.DeserializeAsync(resultStream); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /tests/Compilation/Utils/IntrinsicNodeDeserializer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | using YamlDotNet.Core; 5 | using YamlDotNet.Core.Events; 6 | using YamlDotNet.Serialization; 7 | 8 | namespace Lambdajection.Utils 9 | { 10 | public class IntrinsicNodeDeserializer : INodeDeserializer 11 | { 12 | private readonly HashSet intrinsicFunctionShortForms = new() { "!GetAtt", "!Sub" }; 13 | 14 | public bool Deserialize(IParser reader, Type expectedType, Func nestedObjectDeserializer, out object? value) 15 | { 16 | if (reader.Accept(out var scalar)) 17 | { 18 | if (intrinsicFunctionShortForms.Contains(scalar.Tag.ToString())) 19 | { 20 | value = $"{scalar.Tag} {scalar.Value}"; 21 | reader.MoveNext(); 22 | return true; 23 | } 24 | } 25 | 26 | value = null; 27 | return false; 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /tests/Compilation/Utils/IntrinsicNodeTypeResolver.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | using YamlDotNet.Core.Events; 5 | using YamlDotNet.Serialization; 6 | 7 | namespace Lambdajection.Utils 8 | { 9 | public class IntrinsicNodeTypeResolver : INodeTypeResolver 10 | { 11 | private readonly HashSet intrinsicFunctionShortForms = new() { "!GetAtt", "!Sub" }; 12 | 13 | public bool Resolve(NodeEvent? nodeEvent, ref Type currentType) 14 | { 15 | if (!string.IsNullOrEmpty(nodeEvent?.Tag.ToString()) && intrinsicFunctionShortForms.Contains(nodeEvent?.Tag.ToString() ?? string.Empty)) 16 | { 17 | currentType = typeof(string); 18 | return true; 19 | } 20 | 21 | return false; 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /tests/Setup.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Build.Locator; 2 | 3 | using NUnit.Framework; 4 | 5 | using static System.Environment; 6 | 7 | [SetUpFixture] 8 | public class Setup 9 | { 10 | [OneTimeSetUp] 11 | public void SetupEnvironmentVariables() 12 | { 13 | SetEnvironmentVariable("AWS_REGION", "us-east-1"); 14 | SetEnvironmentVariable("AWS_SECRET_ACCESS_KEY", "AWS_SECRET_ACCESS_KEY"); 15 | SetEnvironmentVariable("AWS_ACCESS_KEY_ID", "AWS_ACCESS_KEY_ID"); 16 | } 17 | 18 | [OneTimeSetUp] 19 | public void RegisterMSBuildAssemblies() 20 | { 21 | MSBuildLocator.RegisterDefaults(); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /tests/TestMetadata.txt: -------------------------------------------------------------------------------- 1 | internal class TestMetadata 2 | { 3 | public static string TestDirectory => @"__TestDirectory__"; 4 | 5 | public static string PackageVersion => "__PackageVersion__"; 6 | 7 | public static string BaseOutputPath => @"__BaseOutputPath__"; 8 | 9 | public static string BaseIntermediateOutputPath => @"__BaseIntermediateOutputPath__"; 10 | 11 | public static string OutputPath => @"__OutputPath__"; 12 | 13 | public static string RestorePackagesPath => @"__BaseIntermediateOutputPath__"; 14 | 15 | public static string TargetFramework => "__TargetFramework__"; 16 | 17 | public static string Configuration => "__Configuration__"; 18 | } -------------------------------------------------------------------------------- /tests/Unit/Core/LambdaConfigFactoryTests.cs: -------------------------------------------------------------------------------- 1 | using FluentAssertions; 2 | 3 | using Microsoft.Extensions.Configuration.EnvironmentVariables; 4 | 5 | using NUnit.Framework; 6 | 7 | namespace Lambdajection.Core.Tests 8 | { 9 | [Category("Unit")] 10 | public class LambdaConfigFactoryTests 11 | { 12 | [Test, Auto] 13 | public void CreateShouldAddEnvironmentVariables( 14 | [Target] LambdaConfigFactory factory 15 | ) 16 | { 17 | var configuration = factory.Create(); 18 | configuration.Providers.Should().Contain(provider => provider.GetType() == typeof(EnvironmentVariablesConfigurationProvider)); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /tests/Unit/CustomResource/CustomResourceRequestTypeTests.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json; 2 | 3 | using FluentAssertions; 4 | 5 | using NUnit.Framework; 6 | 7 | namespace Lambdajection.CustomResource.Tests 8 | { 9 | [Category("Unit")] 10 | public class CustomResourceRequestTypeTests 11 | { 12 | [Test, Auto] 13 | public void ShouldDeserializeCreate() 14 | { 15 | var source = "\"Create\""; 16 | var result = JsonSerializer.Deserialize(source); 17 | 18 | result.Should().Be(CustomResourceRequestType.Create); 19 | } 20 | 21 | [Test, Auto] 22 | public void ShouldDeserializeUpdate() 23 | { 24 | var source = "\"Update\""; 25 | var result = JsonSerializer.Deserialize(source); 26 | 27 | result.Should().Be(CustomResourceRequestType.Update); 28 | } 29 | 30 | [Test, Auto] 31 | public void ShouldDeserializeDelete() 32 | { 33 | var source = "\"Delete\""; 34 | var result = JsonSerializer.Deserialize(source); 35 | 36 | result.Should().Be(CustomResourceRequestType.Delete); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /tests/Unit/Sns/Helpers/TestSnsLambda.cs: -------------------------------------------------------------------------------- 1 | using System.Threading; 2 | using System.Threading.Tasks; 3 | 4 | using Lambdajection.Sns; 5 | 6 | namespace Lambdajection 7 | { 8 | public class TestSnsLambda : ISnsEventHandler 9 | { 10 | public object Request { get; set; } = null!; 11 | 12 | public virtual Task Handle(SnsMessage request, CancellationToken cancellationToken = default) 13 | { 14 | Request = request; 15 | 16 | return Task.FromResult(null!); 17 | } 18 | 19 | public virtual void Validate(SnsMessage request) 20 | { 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /tests/Utils/CompilationExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Linq; 4 | using System.Runtime.Loader; 5 | 6 | using Microsoft.CodeAnalysis; 7 | using Microsoft.CodeAnalysis.CSharp; 8 | 9 | public static class CompilationExtensions 10 | { 11 | public static GenerateAssemblyResult GenerateAssembly(this Compilation compilation) 12 | { 13 | var options = new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary) 14 | .WithPlatform(Platform.AnyCpu) 15 | .WithOptimizationLevel(OptimizationLevel.Release); 16 | 17 | var diagnostics = compilation.GetDiagnostics(); 18 | if (diagnostics.Where(diagnostic => diagnostic.Severity == DiagnosticSeverity.Error).Any()) 19 | { 20 | throw new Exception("Compilation failed to generate\n" + string.Join('\n', diagnostics.Select(diagnostic => diagnostic.GetMessage()))); 21 | } 22 | 23 | using var stream = new MemoryStream(); 24 | compilation.WithOptions(options).Emit(stream); 25 | stream.Position = 0; 26 | 27 | var context = new AssemblyLoadContext(Path.GetRandomFileName(), true); 28 | return new GenerateAssemblyResult 29 | { 30 | Assembly = context.LoadFromStream(stream), 31 | LoadContext = context, 32 | }; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /tests/Utils/GenerateAssemblyResult.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection; 3 | using System.Runtime.Loader; 4 | 5 | #pragma warning disable CA1063 6 | public class GenerateAssemblyResult : IDisposable 7 | { 8 | public Assembly Assembly { get; set; } = null!; 9 | 10 | public AssemblyLoadContext LoadContext { get; set; } = null!; 11 | 12 | public void Deconstruct(out Assembly assembly) 13 | { 14 | assembly = Assembly; 15 | } 16 | 17 | public void Deconstruct(out Assembly assembly, out AssemblyLoadContext context) 18 | { 19 | assembly = Assembly; 20 | context = LoadContext; 21 | } 22 | 23 | public void Dispose() 24 | { 25 | LoadContext.Unload(); 26 | GC.SuppressFinalize(this); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /tests/Utils/StreamUtils.cs: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | using System.Text.Json; 3 | using System.Threading.Tasks; 4 | 5 | public class StreamUtils 6 | { 7 | public static async Task CreateJsonStream(TInput input, JsonSerializerOptions? options = null) 8 | { 9 | options ??= new JsonSerializerOptions(); 10 | var stream = new MemoryStream(); 11 | await JsonSerializer.SerializeAsync(stream, input, options); 12 | stream.Position = 0; 13 | return stream; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /version.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://raw.githubusercontent.com/AArnott/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", 3 | "version": "0.10.0-beta3", 4 | "publicReleaseRefSpec": [ 5 | "^refs/tags/v\\d\\.\\d" 6 | ] 7 | } --------------------------------------------------------------------------------