/// <summary>
/// Create a Lambda Function or return the ARN of the existing Lambda Function with the same name.
/// </summary>
/// <param name="client"></param>
/// <param name="functionName">Name of lambda function.</param>
/// <param name="functionHandlerName">The name of the .js file that contains the Lambda handler.
/// e.g helloworld.js has functionHandlerName "helloworld". </param>
/// <param name="code">The Base64-encoded zip file of the code to be used. The name of the file
/// in the zip file that contains the Lambda functio handler should match functionHandlerName.
/// .Net 2.0 does not support System.IO.Compression.ZipArchive so the process of creating the
/// Base64-encoded zip file should be done outside of the test framework in the following way:
/// private static string CreateScriptBytesBase64(string name, string script)
/// {
/// using (var stream = new MemoryStream())
/// {
/// using (var archive = new ZipArchive(stream, ZipArchiveMode.Create, true))
/// {
/// var entry = archive.CreateEntry(name + ".js");
/// using (var entryStream = entry.Open())
/// using (var writer = new StreamWriter(entryStream))
/// {
/// writer.Write(script);
/// }
/// }
/// var bytes = stream.ToArray();
/// var base64 = Convert.ToBase64String(bytes);
/// return base64;
/// }
/// }
/// </param>
/// <param name="iamRoleArn"></param>
/// <returns></returns>
public static string CreateFunctionIfNotExists(AmazonLambdaClient client, string functionName, string functionHandlerName, string code, string iamRoleArn)
{
AutoResetEvent ars = new AutoResetEvent(false);
Exception responseException = new Exception();
string functionArn = UtilityMethods.GetFunctionArnIfExists(client, functionName);
if (functionArn == null)
{
int retries = 3;
long codeSize = -1;
while (retries > 0)
{
client.CreateFunctionAsync(new CreateFunctionRequest
{
FunctionName = functionName,
Code = new FunctionCode
{
ZipFile = GetScriptStream(code)
},
Handler = functionHandlerName + ".handler",
Runtime = Runtime.Nodejs,
Description = "Feel free to delete this function. The tests will recreate it when needed.",
Role = iamRoleArn
}, (response) =>
{
responseException = response.Exception;
if (responseException == null)
{
functionArn = response.Response.FunctionArn;
codeSize = response.Response.CodeSize;
}
ars.Set();
}, new AsyncOptions { ExecuteCallbackOnMainThread = false });
ars.WaitOne();
if (responseException == null)
{
break;
}
else
{
Utils.AssertTrue(responseException is InvalidParameterValueException);
// Need to wait longer for eventual consistency of role
retries--;
Thread.Sleep(TimeSpan.FromSeconds(10));
}
}
Assert.IsNotNull(functionArn);
Utils.AssertTrue(codeSize > 0);
}
return functionArn;
}