Skip to content

Instantly share code, notes, and snippets.

@NeilBostrom
Last active June 6, 2018 15:03
Show Gist options
  • Save NeilBostrom/97048a42e536a3b94f37dce2e4ac0c38 to your computer and use it in GitHub Desktop.
Save NeilBostrom/97048a42e536a3b94f37dce2e4ac0c38 to your computer and use it in GitHub Desktop.
Custom resource support for .NET Core Lambda functions
...
"LambdaGetLatestAMI": {
"Type": "AWS::CloudFormation::CustomResource",
"Properties": {
"ServiceToken": "arn:aws:lambda:eu-west-1:123456789012:function:dev-ops-stack-GetLatestAMIAsync-4N4U4OD0C8M3",
"Region": { "Ref": "AWS::Region" }
}
},
...
using Amazon.Lambda.Core;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
namespace DevOpsLambdas
{
public class CloudFormationRequest
{
public string StackId { get; set; }
public string ResponseURL { get; set; }
public string RequestType { get; set; }
public string ResourceType { get; set; }
public string RequestId { get; set; }
public string LogicalResourceId { get; set; }
}
public class CloudFormationResponse
{
public string Status { get; set; }
public string Reason { get; set; }
public string PhysicalResourceId { get; set; }
public string StackId { get; set; }
public string RequestId { get; set; }
public string LogicalResourceId { get; set; }
public object Data { get; set; }
public static async Task<CloudFormationResponse> CompleteCloudFormationResponse(object data, CloudFormationRequest request, ILambdaContext context)
{
var responseBody = new CloudFormationResponse
{
Status = data is Exception ? "FAILED" : "SUCCESS",
Reason = "See the details in CloudWatch Log Stream: " + context.LogStreamName,
PhysicalResourceId = context.LogStreamName,
StackId = request.StackId,
RequestId = request.RequestId,
LogicalResourceId = request.LogicalResourceId,
Data = data
};
try
{
HttpClient client = new HttpClient(new LoggingHandler(new HttpClientHandler()));
var jsonContent = new StringContent(JsonConvert.SerializeObject(responseBody));
jsonContent.Headers.Remove("Content-Type");
var postResponse = await client.PutAsync(request.ResponseURL, jsonContent);
postResponse.EnsureSuccessStatusCode();
}
catch (Exception ex)
{
LambdaLogger.Log("Exception: " + ex.ToString());
responseBody.Status = "FAILED";
responseBody.Data = ex;
}
return responseBody;
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Threading.Tasks;
using Amazon.Lambda.Core;
using Amazon;
using Amazon.EC2;
using Newtonsoft.Json;
using Amazon.EC2.Model;
using System.Net.Http;
using System.Text;
// Assembly attribute to enable the Lambda function's JSON input to be converted into a .NET class.
[assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.Json.JsonSerializer))]
namespace DevOpsLambdas
{
public class Functions
{
public async Task<CloudFormationResponse> GetLatestAMIAsync(GetLatestAMIRequest request, ILambdaContext context)
{
LambdaLogger.Log("GetLatestAMIAsync invoked: " + JsonConvert.SerializeObject(request));
if (request.RequestType != "Delete")
{
var client = new AmazonEC2Client(RegionEndpoint.GetBySystemName(request.ResourceProperties.Region));
var images = await client.DescribeImagesAsync(new DescribeImagesRequest()
{
Filters = new List<Filter> { new Filter("name", new List<string>() { "Windows_Server-2016-English-Full-Base-*" }) },
Owners = new List<string>() { "amazon" }
});
var latestImage = images.Images.OrderByDescending(i => i.CreationDate).Take(1).FirstOrDefault();
string imageId = latestImage.ImageId;
return await CloudFormationResponse.CompleteCloudFormationResponse(new { ImageId = imageId }, request, context);
}
return await CloudFormationResponse.CompleteCloudFormationResponse(null, request, context);
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace DevOpsLambdas
{
public class GetLatestAMIRequest : CloudFormationRequest
{
public ResourcePropertiesModel ResourceProperties { get; set; }
public class ResourcePropertiesModel
{
public string Region { get; set; }
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment