diff --git a/builtin/providers/aws/resource_aws_lambda_function.go b/builtin/providers/aws/resource_aws_lambda_function.go index c7756c397..f33b0521b 100644 --- a/builtin/providers/aws/resource_aws_lambda_function.go +++ b/builtin/providers/aws/resource_aws_lambda_function.go @@ -15,6 +15,7 @@ import ( "github.com/hashicorp/terraform/helper/resource" "github.com/hashicorp/terraform/helper/schema" + "github.com/hashicorp/terraform/helper/validation" ) const awsMutexLambdaKey = `aws_lambda_function` @@ -174,6 +175,22 @@ func resourceAwsLambdaFunction() *schema.Resource { }, }, + "tracing_config": { + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "mode": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringInSlice([]string{"Active", "PassThrough"}, true), + }, + }, + }, + }, + "kms_key_arn": { Type: schema.TypeString, Optional: true, @@ -277,6 +294,14 @@ func resourceAwsLambdaFunctionCreate(d *schema.ResourceData, meta interface{}) e } } + if v, ok := d.GetOk("tracing_config"); ok { + tracingConfig := v.([]interface{}) + tracing := tracingConfig[0].(map[string]interface{}) + params.TracingConfig = &lambda.TracingConfig{ + Mode: aws.String(tracing["mode"].(string)), + } + } + if v, ok := d.GetOk("environment"); ok { environments := v.([]interface{}) environment, ok := environments[0].(map[string]interface{}) @@ -388,6 +413,14 @@ func resourceAwsLambdaFunctionRead(d *schema.ResourceData, meta interface{}) err d.Set("dead_letter_config", []interface{}{}) } + if function.TracingConfig != nil { + d.Set("tracing_config", []interface{}{ + map[string]interface{}{ + "mode": *function.TracingConfig.Mode, + }, + }) + } + // List is sorted from oldest to latest // so this may get costly over time :'( var lastVersion, lastQualifiedArn string @@ -549,6 +582,16 @@ func resourceAwsLambdaFunctionUpdate(d *schema.ResourceData, meta interface{}) e configUpdate = true } } + if d.HasChange("tracing_config") { + tracingConfig := d.Get("tracing_config").([]interface{}) + if len(tracingConfig) == 1 { // Schema guarantees either 0 or 1 + config := tracingConfig[0].(map[string]interface{}) + configReq.TracingConfig = &lambda.TracingConfig{ + Mode: aws.String(config["mode"].(string)), + } + configUpdate = true + } + } if d.HasChange("runtime") { configReq.Runtime = aws.String(d.Get("runtime").(string)) configUpdate = true diff --git a/builtin/providers/aws/resource_aws_lambda_function_test.go b/builtin/providers/aws/resource_aws_lambda_function_test.go index 4ab262f6f..5b76e1ef6 100644 --- a/builtin/providers/aws/resource_aws_lambda_function_test.go +++ b/builtin/providers/aws/resource_aws_lambda_function_test.go @@ -232,6 +232,39 @@ func TestAccAWSLambdaFunction_DeadLetterConfig(t *testing.T) { }) } +func TestAccAWSLambdaFunction_tracingConfig(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: testAccAWSLambdaConfigWithTracingConfig(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", "tracing_config.0.mode", "Active"), + ), + }, + { + Config: testAccAWSLambdaConfigWithTracingConfigUpdated(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", "tracing_config.0.mode", "PassThrough"), + ), + }, + }, + }) +} + func TestAccAWSLambdaFunction_VPC(t *testing.T) { var conf lambda.GetFunctionOutput @@ -825,6 +858,15 @@ resource "aws_iam_role_policy" "iam_policy_for_lambda" { "Resource": [ "*" ] + }, + { + "Effect": "Allow", + "Action": [ + "xray:PutTraceSegments" + ], + "Resource": [ + "*" + ] } ] } @@ -1038,6 +1080,40 @@ resource "aws_lambda_function" "lambda_function_test" { `, rName) } +func testAccAWSLambdaConfigWithTracingConfig(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" + + tracing_config { + mode = "Active" + } +} + +`, rName) +} + +func testAccAWSLambdaConfigWithTracingConfigUpdated(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" + + tracing_config { + mode = "PassThrough" + } +} + +`, rName) +} + func testAccAWSLambdaConfigWithDeadLetterConfig(rName, rSt string) string { return fmt.Sprintf(baseAccAWSLambdaConfig(rSt)+` resource "aws_lambda_function" "lambda_function_test" { diff --git a/website/source/docs/providers/aws/r/lambda_function.html.markdown b/website/source/docs/providers/aws/r/lambda_function.html.markdown index ad6116e9f..2b5d5074f 100644 --- a/website/source/docs/providers/aws/r/lambda_function.html.markdown +++ b/website/source/docs/providers/aws/r/lambda_function.html.markdown @@ -85,13 +85,21 @@ large files efficiently. * `source_code_hash` - (Optional) Used to trigger updates. Must be set to a base64-encoded SHA256 hash of the package file specified with either `filename` or `s3_key`. The usual way to set this is `${base64sha256(file("file.zip"))}`, where "file.zip" is the local filename of the lambda function source archive. * `tags` - (Optional) A mapping of tags to assign to the object. -**dead\_letter\_config** is a child block with a single argument: +**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. +**tracing_config** is a child block with a single argument: + +* `mode` - (Required) Can be either `PassThrough` or `Active`. If PassThrough, Lambda will only trace + the request from an upstream service if it contains a tracing header with + "sampled=1". If Active, Lambda will respect any tracing header it receives + from an upstream service. If no tracing header is received, Lambda will call + X-Ray for a tracing decision. + **vpc\_config** requires the following: * `subnet_ids` - (Required) A list of subnet IDs associated with the Lambda function.