Created
September 6, 2019 15:07
-
-
Save ApocDev/11ce0d06ad06a0d63f67bbf184aa388b to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Net.Http; | |
using System.Threading.Tasks; | |
using Amazon.Lambda.Core; | |
using Newtonsoft.Json; | |
using Newtonsoft.Json.Linq; | |
namespace CloudFormationCustomResourceEvents | |
{ | |
public abstract class CloudFormationCustomResourceFunction<T> where T : CloudFormationResourceProperties | |
{ | |
public virtual async Task<CloudFormationResponse<T>> FunctionHandler(JToken input, ILambdaContext context) | |
{ | |
LambdaLogger.Log("Received Event: " + input); | |
var req = input.ToObject<CloudFormationCustomResourceEventCommon<T>>(); | |
try | |
{ | |
switch (req.RequestType.ToUpperInvariant()) | |
{ | |
case "CREATE": | |
return await CloudFormationResponse<T> | |
.CompleteCloudFormationResponse( | |
await Create(input.ToObject<CloudFormationCustomResourceCreateEvent<T>>(), context) | |
.ConfigureAwait(false), req, context).ConfigureAwait(false); | |
case "UPDATE": | |
return await CloudFormationResponse<T> | |
.CompleteCloudFormationResponse( | |
await Update(input.ToObject<CloudFormationCustomResourceUpdateEvent<T>>(), context) | |
.ConfigureAwait(false), req, context).ConfigureAwait(false); | |
case "DELETE": | |
return await CloudFormationResponse<T> | |
.CompleteCloudFormationResponse( | |
await Delete(input.ToObject<CloudFormationCustomResourceDeleteEvent<T>>(), context) | |
.ConfigureAwait(false), req, context).ConfigureAwait(false); | |
default: | |
// Some unknown request type was sent | |
throw new ArgumentOutOfRangeException(nameof(req.RequestType), | |
"RequestType is invalid. Received: " + req.RequestType); | |
} | |
} | |
catch (Exception ex) | |
{ | |
return await CloudFormationResponse<T>.CompleteCloudFormationResponse(ex, req, context); | |
} | |
} | |
protected abstract Task<object> Create(CloudFormationCustomResourceCreateEvent<T> evt, ILambdaContext context); | |
protected abstract Task<object> Update(CloudFormationCustomResourceUpdateEvent<T> evt, ILambdaContext context); | |
protected abstract Task<object> Delete(CloudFormationCustomResourceDeleteEvent<T> evt, ILambdaContext context); | |
} | |
public class CloudFormationResourceProperties | |
{ | |
public string ServiceToken { get; set; } | |
} | |
public class CloudFormationCustomResourceCreateEvent<T> : CloudFormationCustomResourceEventCommon<T> | |
where T : CloudFormationResourceProperties | |
{ | |
} | |
public class CloudFormationCustomResourceUpdateEvent<T> : CloudFormationCustomResourceEventCommon<T> | |
where T : CloudFormationResourceProperties | |
{ | |
public string PhysicalResourceId { get; set; } | |
public T OldResourceProperties { get; set; } | |
} | |
public class CloudFormationCustomResourceDeleteEvent<T> : CloudFormationCustomResourceEventCommon<T> | |
where T : CloudFormationResourceProperties | |
{ | |
public string PhysicalResourceId { get; set; } | |
} | |
public class CloudFormationCustomResourceEventCommon<T> where T : CloudFormationResourceProperties | |
{ | |
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 T ResourceProperties { get; set; } | |
} | |
public class CloudFormationResponse<T> where T : CloudFormationResourceProperties | |
{ | |
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<T>> CompleteCloudFormationResponse(object data, | |
CloudFormationCustomResourceEventCommon<T> request, ILambdaContext context) | |
{ | |
var responseBody = new CloudFormationResponse<T> | |
{ | |
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 | |
{ | |
using (var client = new HttpClient()) | |
{ | |
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); | |
responseBody.Status = "FAILED"; | |
responseBody.Data = ex; | |
} | |
return responseBody; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment