private async Task CreateFunctionAsync() { var tryCount = 3; while (true) { try { await _lambdaClient.CreateFunctionAsync(new CreateFunctionRequest { FunctionName = _functionName, Code = new FunctionCode { ImageUri = _imageUri }, MemorySize = 512, Role = _executionRoleArn, PackageType = PackageType.Image }); break; } catch (InvalidParameterValueException) { tryCount--; if (tryCount == 0) { throw; } // Wait another 5 seconds to let execution role propagate await Task.Delay(5000); } } var endTime = DateTime.Now.AddSeconds(30); var isActive = false; while (DateTime.Now < endTime) { var response = await _lambdaClient.GetFunctionConfigurationAsync(new GetFunctionConfigurationRequest { FunctionName = _functionName }); if (response.State == State.Active) { isActive = true; break; } await Task.Delay(2000); } if (!isActive) { throw new Exception($"Timed out trying to create Lambda function {_functionName}"); } }
/// <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.Nodejs43, 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); }
internal static async Task <CreateFunctionResponse> CreateFunctionAsync ( this AmazonLambdaClient client, AppPackage package, ASPNetServerLessPublishAWSLambdaConfigSection lambdaConfig, Runtime lambdaRuntime, CancellationToken cancellationToken = default(CancellationToken) ) { var environmentVariables = new Dictionary <string, string>(lambdaConfig.EnvironmentVAriables); var functionTags = new Dictionary <string, string> { { "Name", lambdaConfig.FunctionName } }; var response = (CreateFunctionResponse)null; using (var packageStream = new MemoryStream(package.PackageBytes)) { var createFunctionRequest = new CreateFunctionRequest() { Code = new FunctionCode() { ZipFile = packageStream }, Environment = new Environment() { Variables = environmentVariables }, FunctionName = lambdaConfig.FunctionName, Handler = lambdaConfig.FunctionHandler, MemorySize = lambdaConfig.FunctionMemory.Value, Role = lambdaConfig.FunctionRole, Tags = functionTags, Timeout = lambdaConfig.FunctionTimeoutSeconds.Value, Runtime = lambdaRuntime }; response = await client.CreateFunctionAsync(createFunctionRequest, cancellationToken).ConfigureAwait(false); createFunctionRequest = null; } functionTags = null; environmentVariables = null; return(response); }
private static async Task CreateFunctionAsync(AmazonLambdaClient lambdaClient, string bucketName) { await DeleteFunctionIfExistsAsync(lambdaClient); var createRequest = new CreateFunctionRequest { FunctionName = FunctionName, Code = new FunctionCode { S3Bucket = bucketName, S3Key = DeploymentZipKey }, Handler = "PingAsync", MemorySize = 512, Runtime = Runtime.Provided, Role = ExecutionRoleArn }; var startTime = DateTime.Now; var created = false; while (DateTime.Now < startTime.AddSeconds(30)) { try { await lambdaClient.CreateFunctionAsync(createRequest); created = true; break; } catch (InvalidParameterValueException ipve) { // Wait for the role to be fully propagated through AWS if (ipve.Message == "The role defined for the function cannot be assumed by Lambda.") { await Task.Delay(2000); } else { throw; } } } if (!created) { throw new Exception($"Timed out trying to create Lambda function {FunctionName}"); } }
/// <summary> /// Updates the AWS Lambda functions code. /// </summary> /// <param name="functionName">The name of an AWS Lambda function.</param> /// <param name="settings">The <see cref="UpdateFunctionCodeSettings"/> used during the request to AWS.</param> /// <param name="cancellationToken">A cancellation token that can be used by other objects or threads to receive notice of cancellation.</param> public async Task <string> CreateFunction(string functionName, CreateFunctionSettings settings, CancellationToken cancellationToken = default(CancellationToken)) { if (String.IsNullOrEmpty(functionName)) { throw new ArgumentNullException(nameof(functionName)); } // Create Request AmazonLambdaClient client = this.CreateClient(settings); CreateFunctionRequest request = new CreateFunctionRequest() { FunctionName = functionName, Handler = settings.Handler, Runtime = Runtime.FindValue(settings.Runtime), Role = settings.Role, Environment = new Amazon.Lambda.Model.Environment() { Variables = settings.Environment }, Timeout = settings.Timeout, MemorySize = settings.MemorySize, Publish = settings.Publish, KMSKeyArn = settings.KMSKeyArn, Tags = settings.Tags, Description = settings.Description, Code = new FunctionCode() { S3Bucket = settings.S3Bucket, S3Key = settings.S3Key, S3ObjectVersion = settings.S3Version, } }; if (!String.IsNullOrEmpty(settings.DeadLetterConfig)) { request.DeadLetterConfig.TargetArn = settings.DeadLetterConfig; } if (settings.ZipPath != null) { request.Code.ZipFile = this.GetFileStream(settings.ZipPath, settings); } if (settings.VpcSecurityGroupIds.Count > 0) { request.VpcConfig.SecurityGroupIds = settings.VpcSecurityGroupIds; } if (settings.VpcSubnetIds.Count > 0) { request.VpcConfig.SubnetIds = settings.VpcSubnetIds; } // Check Response CreateFunctionResponse response = await client.CreateFunctionAsync(request, cancellationToken); if (response.HttpStatusCode == HttpStatusCode.OK) { _Log.Verbose("Successfully updated function '{0}'", functionName); return(response.Version); } else { _Log.Error("Failed to update function '{0}'", functionName); return(""); } }