Skip to content

Commit

Permalink
Merge pull request #7 from sagittaras/issue/lambda-module
Browse files Browse the repository at this point in the history
Lambda module
  • Loading branch information
JZechy authored Feb 6, 2024
2 parents 1cf55cb + b170701 commit 52f7612
Show file tree
Hide file tree
Showing 34 changed files with 1,235 additions and 0 deletions.
42 changes: 42 additions & 0 deletions CDK.Framework.sln
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,18 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sagittaras.CDK.Tests.CodeBu
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sagittaras.CDK.Testing.CodePipeline", "Sagittaras.CDK.Testing.CodePipeline\Sagittaras.CDK.Testing.CodePipeline.csproj", "{AE2CE059-04E9-481B-BDCA-28F8C84081D5}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sagittaras.CDK.Framework.Lambda", "Sagittaras.CDK.Framework.Lambda\Sagittaras.CDK.Framework.Lambda.csproj", "{62A39295-39AA-4D7A-B9DA-49E41FF7748B}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sagittaras.CDK.Testing.Lambda", "Sagittaras.CDK.Testing.Lambda\Sagittaras.CDK.Testing.Lambda.csproj", "{126FDC69-6A66-482C-8300-21BA741C85CF}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sagittaras.CDK.Tests.Lambda", "Sagittaras.CDK.Tests.Lambda\Sagittaras.CDK.Tests.Lambda.csproj", "{068ADC7D-C3F2-47C7-AB7B-9C7CC18DAEF3}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sagittaras.CDK.Framework.CodeDeploy", "Sagittaras.CDK.Framework.CodeDeploy\Sagittaras.CDK.Framework.CodeDeploy.csproj", "{A3EB3178-E99C-43DA-AAD8-B0DB3854F234}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sagittaras.CDK.Testing.CodeDeploy", "Sagittaras.CDK.Testing.CodeDeploy\Sagittaras.CDK.Testing.CodeDeploy.csproj", "{0155B525-1934-4085-9F7A-308802DE166C}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sagittaras.CDK.Tests.CodeDeploy", "Sagittaras.CDK.Tests.CodeDeploy\Sagittaras.CDK.Tests.CodeDeploy.csproj", "{F4979529-5489-46DC-86DA-BEE653511C3A}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -84,6 +96,12 @@ Global
{D8E118A5-A14C-4498-808A-BFFF425209F4} = {3A01C380-5151-4039-A00C-A33687E00861}
{26D61AA8-0D2F-4DC0-AB14-A614CEC50C9D} = {F2C4D978-97A6-4451-AAD2-16EDCA158D97}
{AE2CE059-04E9-481B-BDCA-28F8C84081D5} = {3A01C380-5151-4039-A00C-A33687E00861}
{62A39295-39AA-4D7A-B9DA-49E41FF7748B} = {506BD5FC-1E9D-47D4-A609-F977EDF69184}
{126FDC69-6A66-482C-8300-21BA741C85CF} = {3A01C380-5151-4039-A00C-A33687E00861}
{068ADC7D-C3F2-47C7-AB7B-9C7CC18DAEF3} = {F2C4D978-97A6-4451-AAD2-16EDCA158D97}
{A3EB3178-E99C-43DA-AAD8-B0DB3854F234} = {506BD5FC-1E9D-47D4-A609-F977EDF69184}
{0155B525-1934-4085-9F7A-308802DE166C} = {3A01C380-5151-4039-A00C-A33687E00861}
{F4979529-5489-46DC-86DA-BEE653511C3A} = {F2C4D978-97A6-4451-AAD2-16EDCA158D97}
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{940EEEA3-A068-4793-A44A-D2FCE1143E49}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
Expand Down Expand Up @@ -154,5 +172,29 @@ Global
{AE2CE059-04E9-481B-BDCA-28F8C84081D5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{AE2CE059-04E9-481B-BDCA-28F8C84081D5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{AE2CE059-04E9-481B-BDCA-28F8C84081D5}.Release|Any CPU.Build.0 = Release|Any CPU
{62A39295-39AA-4D7A-B9DA-49E41FF7748B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{62A39295-39AA-4D7A-B9DA-49E41FF7748B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{62A39295-39AA-4D7A-B9DA-49E41FF7748B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{62A39295-39AA-4D7A-B9DA-49E41FF7748B}.Release|Any CPU.Build.0 = Release|Any CPU
{126FDC69-6A66-482C-8300-21BA741C85CF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{126FDC69-6A66-482C-8300-21BA741C85CF}.Debug|Any CPU.Build.0 = Debug|Any CPU
{126FDC69-6A66-482C-8300-21BA741C85CF}.Release|Any CPU.ActiveCfg = Release|Any CPU
{126FDC69-6A66-482C-8300-21BA741C85CF}.Release|Any CPU.Build.0 = Release|Any CPU
{068ADC7D-C3F2-47C7-AB7B-9C7CC18DAEF3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{068ADC7D-C3F2-47C7-AB7B-9C7CC18DAEF3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{068ADC7D-C3F2-47C7-AB7B-9C7CC18DAEF3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{068ADC7D-C3F2-47C7-AB7B-9C7CC18DAEF3}.Release|Any CPU.Build.0 = Release|Any CPU
{A3EB3178-E99C-43DA-AAD8-B0DB3854F234}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A3EB3178-E99C-43DA-AAD8-B0DB3854F234}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A3EB3178-E99C-43DA-AAD8-B0DB3854F234}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A3EB3178-E99C-43DA-AAD8-B0DB3854F234}.Release|Any CPU.Build.0 = Release|Any CPU
{0155B525-1934-4085-9F7A-308802DE166C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0155B525-1934-4085-9F7A-308802DE166C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0155B525-1934-4085-9F7A-308802DE166C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0155B525-1934-4085-9F7A-308802DE166C}.Release|Any CPU.Build.0 = Release|Any CPU
{F4979529-5489-46DC-86DA-BEE653511C3A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F4979529-5489-46DC-86DA-BEE653511C3A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F4979529-5489-46DC-86DA-BEE653511C3A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F4979529-5489-46DC-86DA-BEE653511C3A}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
using Constructs;
using Sagittaras.CDK.Framework.Factory;

namespace Sagittaras.CDK.Framework.CodeDeploy.Applications;

/// <summary>
/// Common factory construct for defining the CodeDeploy applications.
/// </summary>
/// <typeparam name="TApplication">Type of resulting application.</typeparam>
/// <typeparam name="TProps">Properties for the application.</typeparam>
public abstract class CodeDeployFactory<TApplication, TProps> : ConstructFactory<TApplication, TProps>
where TApplication : IConstruct
where TProps : class
{
protected CodeDeployFactory(Construct scope, string applicationName) : base(scope, applicationName)
{
ApplicationName = Cloudspace.ResourceName(applicationName);
}

/// <summary>
/// Name of the application prefixed with the Cloud space name.
/// </summary>
protected string ApplicationName { get; }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
using Amazon.CDK.AWS.CodeDeploy;
using Constructs;

namespace Sagittaras.CDK.Framework.CodeDeploy.Applications;

/// <summary>
/// Factory for creating LambdaApplication.
/// </summary>
public class LambdaApplicationFactory : CodeDeployFactory<LambdaApplication, LambdaApplicationProps>
{
public LambdaApplicationFactory(Construct scope, string applicationName) : base(scope, applicationName)
{
Props = new LambdaApplicationProps
{
ApplicationName = ApplicationName
};
}

/// <inheritdoc />
public override LambdaApplicationProps Props { get; }

/// <inheritdoc />
public override LambdaApplication Construct()
{
return new LambdaApplication(this, "deploy-app", Props);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
using Amazon.CDK.AWS.CloudWatch;
using Constructs;
using Sagittaras.CDK.Framework.Extensions;
using Sagittaras.CDK.Framework.Factory;
using Sagittaras.CDK.Framework.Props;

namespace Sagittaras.CDK.Framework.CodeDeploy.Deployments;

/// <summary>
/// Base factory for creating a deployment group.
/// </summary>
/// <typeparam name="TDeploymentGroup"></typeparam>
/// <typeparam name="TProps"></typeparam>
public abstract class DeploymentGroupFactory<TDeploymentGroup, TProps> : ConstructFactory<TDeploymentGroup, TProps>
where TDeploymentGroup : IConstruct
where TProps : class
{
protected DeploymentGroupFactory(Construct scope, string groupName) : base(scope, groupName)
{
CommonProps = new DeploymentGroupProps
{
DeploymentGroupName = groupName
};
}

/// <summary>
/// Common props for deployment groups.
/// </summary>
private DeploymentGroupProps CommonProps { get; }

/// <inheritdoc />
public override TDeploymentGroup Construct()
{
PropsMapper.Map(CommonProps, Props);
return ConstructDeploymentGroup();
}

/// <summary>
/// Replaces original <see cref="Construct" /> to allow mapping of common properties to the deployment group.
/// </summary>
/// <returns></returns>
protected abstract TDeploymentGroup ConstructDeploymentGroup();

/// <summary>
/// Adds alarms to the deployment group that should watch the deployment.
/// </summary>
/// <param name="alarms"></param>
/// <returns></returns>
public DeploymentGroupFactory<TDeploymentGroup, TProps> AddAlarms(params IAlarm[] alarms)
{
CommonProps.AddAlarms(alarms);

return this;
}

/// <summary>
/// Adds alarms to the deployment group that should watch the deployment.
/// </summary>
/// <remarks>
/// Finds the alarms by their names.
/// </remarks>
/// <param name="alarmNames"></param>
/// <returns></returns>
public DeploymentGroupFactory<TDeploymentGroup, TProps> AddAlarmsByLookup(params string[] alarmNames)
{
IAlarm[] alarms = alarmNames.Select(x => Alarm.FromAlarmName(this, $"alarm-{x.ToResourceId()}", x))
.ToArray();
AddAlarms(alarms);

return this;
}

/// <summary>
/// Configures whether to ignore alarms during deployment.
/// </summary>
/// <param name="ignore"></param>
/// <returns></returns>
public DeploymentGroupFactory<TDeploymentGroup, TProps> IgnoreAlarms(bool ignore)
{
CommonProps.IgnorePollAlarmsFailure = ignore;

return this;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
using Amazon.CDK.AWS.CloudWatch;
using Amazon.CDK.AWS.CodeDeploy;

namespace Sagittaras.CDK.Framework.CodeDeploy.Deployments;

/// <summary>
/// Custom class to group common properties of the deployment groups of different types,
/// to overcome missing base class for deployment groups.
/// </summary>
public class DeploymentGroupProps
{
private readonly List<IAlarm> _alarms = new();

public IAlarm[]? Alarms
{
get => _alarms.Any() ? _alarms.ToArray() : null;
set
{
if (value is null) return;

_alarms.AddRange(value);
}
}

public AutoRollbackConfig AutoRollback { get; set; } = new()
{
FailedDeployment = true,
StoppedDeployment = true
};

public string? DeploymentGroupName { get; set; }
public bool? IgnorePollAlarmsFailure { get; set; }

public void AddAlarms(params IAlarm[] alarms)
{
_alarms.AddRange(alarms);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
using Amazon.CDK.AWS.CodeDeploy;
using Amazon.CDK.AWS.Lambda;
using Constructs;

namespace Sagittaras.CDK.Framework.CodeDeploy.Deployments;

/// <summary>
/// Factory for creating a deployment group for Lambda function.
/// </summary>
public class LambdaDeploymentGroupFactory : DeploymentGroupFactory<LambdaDeploymentGroup, LambdaDeploymentGroupProps>
{
public LambdaDeploymentGroupFactory(Construct scope, string groupName, Function function) : base(scope, groupName)
{
Props = new LambdaDeploymentGroupProps
{
Alias = function.AddAlias("Live", new AliasOptions
{
Description = "Alias for the blue/green deployment."
})
};
}

public LambdaDeploymentGroupFactory(Construct scope, string groupName, Alias alias) : base(scope, groupName)
{
Props = new LambdaDeploymentGroupProps
{
Alias = alias
};
}

/// <inheritdoc />
public override LambdaDeploymentGroupProps Props { get; }

/// <inheritdoc />
protected override LambdaDeploymentGroup ConstructDeploymentGroup()
{
return new LambdaDeploymentGroup(this, "deployment-group", Props);
}

/// <summary>
/// Makes the deployment group part of the application.
/// </summary>
/// <param name="application"></param>
/// <returns></returns>
public LambdaDeploymentGroupFactory PartOf(ILambdaApplication application)
{
Props.Application = application;
return this;
}

/// <summary>
/// Makes the deployment group part of the application.
/// </summary>
/// <remarks>
/// Find the application by its name.
/// </remarks>
/// <param name="applicationName"></param>
/// <returns></returns>
public LambdaDeploymentGroupFactory PartOf(string applicationName)
{
Props.Application = LambdaApplication.FromLambdaApplicationName(this, "application", applicationName);
return this;
}

/// <summary>
/// Configures the deployment strategy for the group.
/// </summary>
/// <param name="config"></param>
/// <returns></returns>
public LambdaDeploymentGroupFactory WithDeploymentConfig(ILambdaDeploymentConfig config)
{
Props.DeploymentConfig = config;
return this;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<Version>1.0.0-preview-01</Version>
<Title>CodeDeploy CDK Framework</Title>
<Description>Framework for easier building fo CodeDeploy with CDK.</Description>
<PackageProjectUrl>https://github.com/sagittaras/cdk.framework</PackageProjectUrl>
<PackageLicenseUrl>https://github.com/sagittaras/cdk.framework/blob/main/LICENSE</PackageLicenseUrl>
<RepositoryUrl>https://github.com/sagittaras/cdk.framework</RepositoryUrl>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\Sagittaras.CDK.Framework\Sagittaras.CDK.Framework.csproj"/>
</ItemGroup>

</Project>
40 changes: 40 additions & 0 deletions Sagittaras.CDK.Framework.Lambda/DockerImageLambdaFactory.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
using Amazon.CDK.AWS.ECR;
using Amazon.CDK.AWS.Lambda;
using Constructs;

namespace Sagittaras.CDK.Framework.Lambda;

/// <summary>
/// Factory creating a Lambda function with usage of Docker Image.
/// </summary>
public class DockerImageLambdaFactory : LambdaFactory<DockerImageFunction, DockerImageFunctionProps>
{
public DockerImageLambdaFactory(Construct scope, string functionName) : base(scope, functionName)
{
}

/// <inheritdoc />
public override DockerImageFunctionProps Props { get; } = new();

/// <inheritdoc />
public override DockerImageFunction Construct()
{
MapCommonProperties(Props);
return new DockerImageFunction(this, "function", Props);
}

/// <summary>
/// Configure the usage of docker image from ECR, based on tag or digest.
/// </summary>
/// <param name="repository"></param>
/// <param name="tagOrDigest"></param>
/// <returns></returns>
public DockerImageLambdaFactory FromEcr(string repository, string tagOrDigest)
{
Props.Code = DockerImageCode.FromEcr(Repository.FromRepositoryName(this, "image-source", repository), new EcrImageCodeProps
{
TagOrDigest = tagOrDigest
});
return this;
}
}
Loading

0 comments on commit 52f7612

Please sign in to comment.