provider/aws: Lambda DeadLetterConfig support
This feature allows sending a notification to either an SQS queue or an SNS topic when an error occurs running an AWS Lambda function. This fixes #10630.
This commit is contained in:
parent
8c9bfb7bfe
commit
db9fbe67fa
|
@ -58,6 +58,22 @@ func resourceAwsLambdaFunction() *schema.Resource {
|
|||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
},
|
||||
"dead_letter_config": {
|
||||
Type: schema.TypeList,
|
||||
Optional: true,
|
||||
ForceNew: true,
|
||||
MinItems: 0,
|
||||
MaxItems: 1,
|
||||
Elem: &schema.Resource{
|
||||
Schema: map[string]*schema.Schema{
|
||||
"target_arn": {
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
ValidateFunc: validateArn,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"function_name": {
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
|
@ -222,6 +238,16 @@ func resourceAwsLambdaFunctionCreate(d *schema.ResourceData, meta interface{}) e
|
|||
Publish: aws.Bool(d.Get("publish").(bool)),
|
||||
}
|
||||
|
||||
if v, ok := d.GetOk("dead_letter_config"); ok {
|
||||
dlcMaps := v.([]interface{})
|
||||
if len(dlcMaps) == 1 { // Schema guarantees either 0 or 1
|
||||
dlcMap := dlcMaps[0].(map[string]interface{})
|
||||
params.DeadLetterConfig = &lambda.DeadLetterConfig{
|
||||
TargetArn: aws.String(dlcMap["target_arn"].(string)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if v, ok := d.GetOk("vpc_config"); ok {
|
||||
config, err := validateVPCConfig(v)
|
||||
if err != nil {
|
||||
|
@ -343,6 +369,16 @@ func resourceAwsLambdaFunctionRead(d *schema.ResourceData, meta interface{}) err
|
|||
log.Printf("[ERR] Error setting environment for Lambda Function (%s): %s", d.Id(), err)
|
||||
}
|
||||
|
||||
if function.DeadLetterConfig != nil && function.DeadLetterConfig.TargetArn != nil {
|
||||
d.Set("dead_letter_config", []interface{}{
|
||||
map[string]interface{}{
|
||||
"target_arn": *function.DeadLetterConfig.TargetArn,
|
||||
},
|
||||
})
|
||||
} else {
|
||||
d.Set("dead_letter_config", []interface{}{})
|
||||
}
|
||||
|
||||
// List is sorted from oldest to latest
|
||||
// so this may get costly over time :'(
|
||||
var lastVersion, lastQualifiedArn string
|
||||
|
@ -485,6 +521,16 @@ func resourceAwsLambdaFunctionUpdate(d *schema.ResourceData, meta interface{}) e
|
|||
configReq.KMSKeyArn = aws.String(d.Get("kms_key_arn").(string))
|
||||
configUpdate = true
|
||||
}
|
||||
if d.HasChange("dead_letter_config") {
|
||||
dlcMaps := d.Get("dead_letter_config").([]interface{})
|
||||
if len(dlcMaps) == 1 { // Schema guarantees either 0 or 1
|
||||
dlcMap := dlcMaps[0].(map[string]interface{})
|
||||
configReq.DeadLetterConfig = &lambda.DeadLetterConfig{
|
||||
TargetArn: aws.String(dlcMap["target_arn"].(string)),
|
||||
}
|
||||
configUpdate = true
|
||||
}
|
||||
}
|
||||
if d.HasChange("environment") {
|
||||
if v, ok := d.GetOk("environment"); ok {
|
||||
environments := v.([]interface{})
|
||||
|
|
|
@ -172,6 +172,37 @@ func TestAccAWSLambdaFunction_versioned(t *testing.T) {
|
|||
})
|
||||
}
|
||||
|
||||
func TestAccAWSLambdaFunction_DeadLetterConfig(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: testAccAWSLambdaConfigWithDeadLetterConfig(rName, rSt),
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
testAccCheckAwsLambdaFunctionExists("aws_lambda_function.lambda_function_test", rName, &conf),
|
||||
testAccCheckAwsLambdaFunctionName(&conf, rName),
|
||||
testAccCheckAwsLambdaFunctionArnHasSuffix(&conf, ":"+rName),
|
||||
func(s *terraform.State) error {
|
||||
if !strings.HasSuffix(*conf.Configuration.DeadLetterConfig.TargetArn, ":"+rName) {
|
||||
return fmt.Errorf(
|
||||
"Expected DeadLetterConfig.TargetArn %s to have suffix %s", *conf.Configuration.DeadLetterConfig.TargetArn, ":"+rName,
|
||||
)
|
||||
}
|
||||
return nil
|
||||
},
|
||||
),
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func TestAccAWSLambdaFunction_VPC(t *testing.T) {
|
||||
var conf lambda.GetFunctionOutput
|
||||
|
||||
|
@ -681,6 +712,15 @@ resource "aws_iam_role_policy" "iam_policy_for_lambda" {
|
|||
"Resource": [
|
||||
"*"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Effect": "Allow",
|
||||
"Action": [
|
||||
"SNS:Publish"
|
||||
],
|
||||
"Resource": [
|
||||
"*"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -879,6 +919,27 @@ resource "aws_lambda_function" "lambda_function_test" {
|
|||
`, rName)
|
||||
}
|
||||
|
||||
func testAccAWSLambdaConfigWithDeadLetterConfig(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"
|
||||
|
||||
dead_letter_config {
|
||||
target_arn = "${aws_sns_topic.lambda_function_test.arn}"
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_sns_topic" "lambda_function_test" {
|
||||
name = "%s"
|
||||
}
|
||||
|
||||
`, rName, rName)
|
||||
}
|
||||
|
||||
func testAccAWSLambdaConfigWithVPC(rName, rSt string) string {
|
||||
return fmt.Sprintf(baseAccAWSLambdaConfig(rSt)+`
|
||||
resource "aws_lambda_function" "lambda_function_test" {
|
||||
|
|
|
@ -57,6 +57,7 @@ resource "aws_lambda_function" "test_lambda" {
|
|||
* `s3_key` - (Optional) The S3 key containing your lambda function source code. Conflicts with `filename`.
|
||||
* `s3_object_version` - (Optional) The object version of your lambda function source code. Conflicts with `filename`.
|
||||
* `function_name` - (Required) A unique name for your Lambda Function.
|
||||
* `dead_letter_config` - (Optional) Nested block to configure the function's *dead letter queue*. See details below.
|
||||
* `handler` - (Required) The function [entrypoint][3] in your code.
|
||||
* `role` - (Required) IAM role attached to the Lambda Function. This governs both who / what can invoke your Lambda Function, as well as what resources our Lambda Function has access to. See [Lambda Permission Model][4] for more details.
|
||||
* `description` - (Optional) Description of what your Lambda Function does.
|
||||
|
@ -70,6 +71,13 @@ resource "aws_lambda_function" "test_lambda" {
|
|||
* `source_code_hash` - (Optional) Used to trigger updates. This is only useful in conjunction with `filename`.
|
||||
The only useful value is `${base64sha256(file("file.zip"))}`.
|
||||
|
||||
**dead\_letter\_config** is a child block with a single argument:
|
||||
|
||||
* `target_arn` - (Required) The ARN of an SNS topic or SQS queue to notify when an invocation fails. If this
|
||||
option is used, the function's IAM role must be granted suitable access to write to the target object,
|
||||
which means allowing either the `sns:Publish` or `sqs:SendMessage` action on this ARN, depending on
|
||||
which service is targeted.
|
||||
|
||||
**vpc\_config** requires the following:
|
||||
|
||||
* `subnet_ids` - (Required) A list of subnet IDs associated with the Lambda function.
|
||||
|
|
Loading…
Reference in New Issue