Skip to content

Commit

Permalink
AWS Lambda concurrency (#2504)
Browse files Browse the repository at this point in the history
  • Loading branch information
Puneeth-n authored and radeksimko committed Dec 5, 2017
1 parent 168287a commit b40e6ef
Show file tree
Hide file tree
Showing 3 changed files with 158 additions and 0 deletions.
54 changes: 54 additions & 0 deletions aws/resource_aws_lambda_function.go
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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
}

Expand Down Expand Up @@ -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)
Expand Down
102 changes: 102 additions & 0 deletions aws/resource_aws_lambda_function_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"),
),
},
},
Expand Down Expand Up @@ -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" {
Expand Down
2 changes: 2 additions & 0 deletions website/docs/r/lambda_function.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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

Expand Down

0 comments on commit b40e6ef

Please sign in to comment.