private Stream GetLambdaEdgeMemoryStreamFromAssembly(DeployLambdaEdgeRequest request) { string embeddedResourcePath = $"{GetType().Namespace}.LambdaEdgeFunctions.{request.ResourceProperties.EmbeddedFileName}"; Stream jsResourceStream = GetType().Assembly.GetManifestResourceStream(embeddedResourcePath); if (jsResourceStream == null) { throw new Exception($"Failed to find an embedded resource at {embeddedResourcePath}"); } string jsText; using (StreamReader reader = new StreamReader(jsResourceStream)) jsText = reader.ReadToEnd(); if (request.ResourceProperties.ReplacementPairs != null) { // Allow a list of replacement pairs in the format of key=value // These can replace %%key%% found in file with the value // For example %%domain%% to the live domain used in the stack foreach (var pair in request.ResourceProperties.ReplacementPairs) { var keyValuePair = pair.Split("="); if (keyValuePair.Length != 2) { throw new Exception($"Found ReplacementPairs \"{pair}\" that did not split into two parts"); } jsText = jsText.Replace($"%%{keyValuePair[0]}%%", keyValuePair[1]); } } return(new MemoryStream(Encoding.UTF8.GetBytes(jsText))); }
public async Task FunctionHandlerAsync(DeployLambdaEdgeRequest request, ILambdaContext context) { try { context.Logger.Log("LambdaEdgeFunction invoked: " + JsonConvert.SerializeObject(request)); if (string.IsNullOrWhiteSpace(request.RequestType)) { throw new ArgumentException($"Missing or empty RequestType"); } string lambdaVersionedArn = null; if (request.RequestType == "Create" || request.RequestType == "Update") { if (string.IsNullOrWhiteSpace(request.ResourceProperties.RoleArn)) { throw new ArgumentException($"Missing or empty ResourceProperties.RoleArn"); } if (string.IsNullOrWhiteSpace(request.ResourceProperties.FunctionName)) { throw new ArgumentException($"Missing or empty ResourceProperties.FunctionName"); } if (string.IsNullOrWhiteSpace(request.ResourceProperties.EmbeddedFileName)) { throw new ArgumentException($"Missing or empty ResourceProperties.EmbeddedFileName"); } Stream lambdaEdgeJsFile = GetLambdaEdgeMemoryStreamFromAssembly(request); MemoryStream zipFile = AddFileStreamToZipAndReturnZipStream(lambdaEdgeJsFile, request.ResourceProperties.EmbeddedFileName); if (request.RequestType == "Create") { var createResponse = await LambdaClient.CreateFunctionAsync(new CreateFunctionRequest { FunctionName = request.ResourceProperties.FunctionName, Handler = $"{Path.GetFileNameWithoutExtension(request.ResourceProperties.EmbeddedFileName)}.handler", Code = new FunctionCode() { ZipFile = zipFile }, Runtime = Runtime.Nodejs610, Publish = true, Role = request.ResourceProperties.RoleArn }); request.PhysicalResourceId = createResponse.FunctionArn; lambdaVersionedArn = $"{createResponse.FunctionArn}:{createResponse.Version}"; } else if (request.RequestType == "Update") { if (request.PhysicalResourceId.StartsWith("arn:aws:lambda:")) { var updateResponse = await LambdaClient.UpdateFunctionCodeAsync(new UpdateFunctionCodeRequest { FunctionName = $"{request.PhysicalResourceId}", ZipFile = zipFile, Publish = true, }); // The FunctionArn sometimes returns the version in it if (updateResponse.FunctionArn.EndsWith(updateResponse.Version)) { lambdaVersionedArn = $"{updateResponse.FunctionArn}"; } else { lambdaVersionedArn = $"{updateResponse.FunctionArn}:{updateResponse.Version}"; } } else { context.Logger.LogLine("PhysicalResourceId was not a lambda resource on UPDATE, skipping update command"); } } } else if (request.RequestType == "Delete") { if (request.PhysicalResourceId.StartsWith("arn:aws:lambda:")) { var updateResponse = await LambdaClient.DeleteFunctionAsync(new DeleteFunctionRequest { FunctionName = $"{request.PhysicalResourceId}" }); } else { context.Logger.LogLine("PhysicalResourceId was not a lambda resource on DELETE, skipping remove command"); } } await CloudFormationResponse.CompleteCloudFormation(new { LambdaVersionedArn = lambdaVersionedArn }, request, context); } catch (Exception ex) { await CloudFormationResponse.FailCloudFormation(ex, request, context); throw; } }