From d47ecc603fd4985b1731efc544f72645cd2a9641 Mon Sep 17 00:00:00 2001 From: Puneeth Nanjundaswamy Date: Thu, 30 Nov 2017 23:02:32 +0100 Subject: [PATCH] AWS Lambda concurrency --- aws/resource_aws_lambda_function.go | 54 ++++++++++ aws/resource_aws_lambda_function_test.go | 102 +++++++++++++++++++ website/docs/r/lambda_function.html.markdown | 2 + 3 files changed, 158 insertions(+) diff --git a/aws/resource_aws_lambda_function.go b/aws/resource_aws_lambda_function.go index d45bdcf92d8c..d16988346c66 100644 --- a/aws/resource_aws_lambda_function.go +++ b/aws/resource_aws_lambda_function.go @@ -88,6 +88,10 @@ func resourceAwsLambdaFunction() *schema.Resource { Optional: true, Default: 128, }, + "reserved_concurrent_executions": { + Type: schema.TypeInt, + Optional: true, + }, "role": { Type: schema.TypeString, Required: true, @@ -205,6 +209,7 @@ func resourceAwsLambdaFunctionCreate(d *schema.ResourceData, meta interface{}) e conn := meta.(*AWSClient).lambdaconn functionName := d.Get("function_name").(string) + reservedConcurrentExecutions := d.Get("reserved_concurrent_executions").(int) iamRole := d.Get("role").(string) log.Printf("[DEBUG] Creating Lambda Function %s with role %s", functionName, iamRole) @@ -355,6 +360,21 @@ func resourceAwsLambdaFunctionCreate(d *schema.ResourceData, meta interface{}) e return fmt.Errorf("Error creating Lambda function: %s", err) } + if reservedConcurrentExecutions > 0 { + + log.Printf("[DEBUG] Setting Concurrency to %d for the Lambda Function %s", reservedConcurrentExecutions, functionName) + + concurrencyParams := &lambda.PutFunctionConcurrencyInput{ + FunctionName: aws.String(functionName), + ReservedConcurrentExecutions: aws.Int64(int64(reservedConcurrentExecutions)), + } + + _, err := conn.PutFunctionConcurrency(concurrencyParams) + if err != nil { + return fmt.Errorf("Error setting concurrency for Lambda %s: %s", functionName, err) + } + } + d.SetId(d.Get("function_name").(string)) return resourceAwsLambdaFunctionRead(d, meta) @@ -453,6 +473,12 @@ func resourceAwsLambdaFunctionRead(d *schema.ResourceData, meta interface{}) err d.Set("invoke_arn", buildLambdaInvokeArn(*function.FunctionArn, meta.(*AWSClient).region)) + if getFunctionOutput.Concurrency != nil { + d.Set("reserved_concurrent_executions", getFunctionOutput.Concurrency.ReservedConcurrentExecutions) + } else { + d.Set("reserved_concurrent_executions", nil) + } + return nil } @@ -667,6 +693,34 @@ func resourceAwsLambdaFunctionUpdate(d *schema.ResourceData, meta interface{}) e d.SetPartial("s3_object_version") } + if d.HasChange("reserved_concurrent_executions") { + nc := d.Get("reserved_concurrent_executions") + + if nc.(int) > 0 { + log.Printf("[DEBUG] Updating Concurrency to %d for the Lambda Function %s", nc.(int), d.Id()) + + concurrencyParams := &lambda.PutFunctionConcurrencyInput{ + FunctionName: aws.String(d.Id()), + ReservedConcurrentExecutions: aws.Int64(int64(d.Get("reserved_concurrent_executions").(int))), + } + + _, err := conn.PutFunctionConcurrency(concurrencyParams) + if err != nil { + return fmt.Errorf("Error setting concurrency for Lambda %s: %s", d.Id(), err) + } + } else { + log.Printf("[DEBUG] Removing Concurrency for the Lambda Function %s", d.Id()) + + deleteConcurrencyParams := &lambda.DeleteFunctionConcurrencyInput{ + FunctionName: aws.String(d.Id()), + } + _, err := conn.DeleteFunctionConcurrency(deleteConcurrencyParams) + if err != nil { + return fmt.Errorf("Error setting concurrency for Lambda %s: %s", d.Id(), err) + } + } + } + d.Partial(false) return resourceAwsLambdaFunctionRead(d, meta) diff --git a/aws/resource_aws_lambda_function_test.go b/aws/resource_aws_lambda_function_test.go index d8e01be69117..a28db1a0d520 100644 --- a/aws/resource_aws_lambda_function_test.go +++ b/aws/resource_aws_lambda_function_test.go @@ -34,6 +34,82 @@ func TestAccAWSLambdaFunction_basic(t *testing.T) { testAccCheckAwsLambdaFunctionExists("aws_lambda_function.lambda_function_test", rName, &conf), testAccCheckAwsLambdaFunctionName(&conf, rName), testAccCheckAwsLambdaFunctionArnHasSuffix(&conf, ":"+rName), + resource.TestCheckResourceAttr("aws_lambda_function.lambda_function_test", "reserved_concurrent_executions", "0"), + ), + }, + }, + }) +} + +func TestAccAWSLambdaFunction_concurrency(t *testing.T) { + var conf lambda.GetFunctionOutput + + rSt := acctest.RandString(5) + rName := fmt.Sprintf("tf_test_%s", rSt) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckLambdaFunctionDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSLambdaConfigBasicConcurrency(rName, rSt), + Check: resource.ComposeTestCheckFunc( + testAccCheckAwsLambdaFunctionExists("aws_lambda_function.lambda_function_test", rName, &conf), + testAccCheckAwsLambdaFunctionName(&conf, rName), + testAccCheckAwsLambdaFunctionArnHasSuffix(&conf, ":"+rName), + resource.TestCheckResourceAttr("aws_lambda_function.lambda_function_test", "reserved_concurrent_executions", "111"), + ), + }, + { + Config: testAccAWSLambdaConfigConcurrencyUpdate(rName, rSt), + Check: resource.ComposeTestCheckFunc( + testAccCheckAwsLambdaFunctionExists("aws_lambda_function.lambda_function_test", rName, &conf), + testAccCheckAwsLambdaFunctionName(&conf, rName), + testAccCheckAwsLambdaFunctionArnHasSuffix(&conf, ":"+rName), + resource.TestCheckResourceAttr("aws_lambda_function.lambda_function_test", "reserved_concurrent_executions", "222"), + ), + }, + }, + }) +} + +func TestAccAWSLambdaFunction_concurrencyCycle(t *testing.T) { + var conf lambda.GetFunctionOutput + + rSt := acctest.RandString(5) + rName := fmt.Sprintf("tf_test_%s", rSt) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckLambdaFunctionDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSLambdaConfigBasic(rName, rSt), + Check: resource.ComposeTestCheckFunc( + testAccCheckAwsLambdaFunctionExists("aws_lambda_function.lambda_function_test", rName, &conf), + testAccCheckAwsLambdaFunctionName(&conf, rName), + testAccCheckAwsLambdaFunctionArnHasSuffix(&conf, ":"+rName), + resource.TestCheckResourceAttr("aws_lambda_function.lambda_function_test", "reserved_concurrent_executions", "0"), + ), + }, + { + Config: testAccAWSLambdaConfigConcurrencyUpdate(rName, rSt), + Check: resource.ComposeTestCheckFunc( + testAccCheckAwsLambdaFunctionExists("aws_lambda_function.lambda_function_test", rName, &conf), + testAccCheckAwsLambdaFunctionName(&conf, rName), + testAccCheckAwsLambdaFunctionArnHasSuffix(&conf, ":"+rName), + resource.TestCheckResourceAttr("aws_lambda_function.lambda_function_test", "reserved_concurrent_executions", "222"), + ), + }, + { + Config: testAccAWSLambdaConfigBasic(rName, rSt), + Check: resource.ComposeTestCheckFunc( + testAccCheckAwsLambdaFunctionExists("aws_lambda_function.lambda_function_test", rName, &conf), + testAccCheckAwsLambdaFunctionName(&conf, rName), + testAccCheckAwsLambdaFunctionArnHasSuffix(&conf, ":"+rName), + resource.TestCheckResourceAttr("aws_lambda_function.lambda_function_test", "reserved_concurrent_executions", "0"), ), }, }, @@ -1069,6 +1145,32 @@ resource "aws_lambda_function" "lambda_function_test" { `, rName) } +func testAccAWSLambdaConfigBasicConcurrency(rName, rSt string) string { + return fmt.Sprintf(baseAccAWSLambdaConfig(rSt)+` +resource "aws_lambda_function" "lambda_function_test" { + filename = "test-fixtures/lambdatest.zip" + function_name = "%s" + role = "${aws_iam_role.iam_for_lambda.arn}" + handler = "exports.example" + runtime = "nodejs4.3" + reserved_concurrent_executions = 111 +} +`, rName) +} + +func testAccAWSLambdaConfigConcurrencyUpdate(rName, rSt string) string { + return fmt.Sprintf(baseAccAWSLambdaConfig(rSt)+` +resource "aws_lambda_function" "lambda_function_test" { + filename = "test-fixtures/lambdatest.zip" + function_name = "%s" + role = "${aws_iam_role.iam_for_lambda.arn}" + handler = "exports.example" + runtime = "nodejs4.3" + reserved_concurrent_executions = 222 +} +`, rName) +} + func testAccAWSLambdaConfigBasicUpdateRuntime(rName, rSt string) string { return fmt.Sprintf(baseAccAWSLambdaConfig(rSt)+` resource "aws_lambda_function" "lambda_function_test" { diff --git a/website/docs/r/lambda_function.html.markdown b/website/docs/r/lambda_function.html.markdown index 98ca76a38b30..6625f8ee9a7b 100644 --- a/website/docs/r/lambda_function.html.markdown +++ b/website/docs/r/lambda_function.html.markdown @@ -78,6 +78,7 @@ large files efficiently. * `memory_size` - (Optional) Amount of memory in MB your Lambda Function can use at runtime. Defaults to `128`. See [Limits][5] * `runtime` - (Required) See [Runtimes][6] for valid values. * `timeout` - (Optional) The amount of time your Lambda Function has to run in seconds. Defaults to `3`. See [Limits][5] +* `reserved_concurrent_executions` - (Optional) The amount of reserved concurrent executions for this lambda function. Defaults to Unreserved Concurrency Limits. See [Managing Concurrency][9] * `publish` - (Optional) Whether to publish creation/change as new Lambda Function Version. Defaults to `false`. * `vpc_config` - (Optional) Provide this to allow your function to access your VPC. Fields documented below. See [Lambda in VPC][7] * `environment` - (Optional) The Lambda environment's configuration settings. Fields documented below. @@ -131,6 +132,7 @@ For **environment** the following attributes are supported: [6]: https://docs.aws.amazon.com/lambda/latest/dg/API_CreateFunction.html#SSS-CreateFunction-request-Runtime [7]: http://docs.aws.amazon.com/lambda/latest/dg/vpc.html [8]: https://docs.aws.amazon.com/lambda/latest/dg/deployment-package-v2.html +[9]: https://docs.aws.amazon.com/lambda/latest/dg/concurrent-executions.html ## Import