Skip to content

Commit

Permalink
resource/aws_lambda_function: Prevent crash with missing environment …
Browse files Browse the repository at this point in the history
…variable value (#17056)

Previously if the environment variable value became `nil` (likely via AWS console update), the resource could panic:

```
{
  "Configuration": {
    ...
    "Environment": {
      "Variables": {
        "XXX": null,
        "YYY": "ZZZ"
      },
      "Error": null
    },
    ...
  },
  ...
}
```

```
panic: runtime error: invalid memory address or nil pointer dereference
2020-12-10T19:59:19.412Z [DEBUG] plugin.terraform-provider-aws_v3.0.0_x5: [signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x401dab7]
2020-12-10T19:59:19.413Z [DEBUG] plugin.terraform-provider-aws_v3.0.0_x5:
2020-12-10T19:59:19.413Z [DEBUG] plugin.terraform-provider-aws_v3.0.0_x5: goroutine 485 [running]:
2020-12-10T19:59:19.413Z [DEBUG] plugin.terraform-provider-aws_v3.0.0_x5: github.com/terraform-providers/terraform-provider-aws/aws.flattenLambdaEnvironment(0xc00162daa0, 0x57add72, 0xa, 0x44b4460)
2020-12-10T19:59:19.413Z [DEBUG] plugin.terraform-provider-aws_v3.0.0_x5: 	/opt/teamcity-agent/work/5d79fe75d4460a2f/src/github.com/terraform-providers/terraform-provider-aws/aws/structure.go:1594 +0xc7
2020-12-10T19:59:19.413Z [DEBUG] plugin.terraform-provider-aws_v3.0.0_x5: github.com/terraform-providers/terraform-provider-aws/aws.resourceAwsLambdaFunctionRead(0xc00016ee00, 0x4c948a0, 0xc000160a00, 0xc00016ee00, 0x0)
2020-12-10T19:59:19.413Z [DEBUG] plugin.terraform-provider-aws_v3.0.0_x5: 	/opt/teamcity-agent/work/5d79fe75d4460a2f/src/github.com/terraform-providers/terraform-provider-aws/aws/resource_aws_lambda_function.go:599 +0x107a
```

This replaces the unsafe dereferencing with the AWS Go SDK conversion function.

Output from acceptance testing:

```
--- PASS: TestAccAWSLambdaFunction_basic (93.45s)
--- PASS: TestAccAWSLambdaFunction_codeSigningConfig (143.84s)
--- PASS: TestAccAWSLambdaFunction_concurrency (119.18s)
--- PASS: TestAccAWSLambdaFunction_concurrencyCycle (80.17s)
--- PASS: TestAccAWSLambdaFunction_DeadLetterConfig (130.84s)
--- PASS: TestAccAWSLambdaFunction_DeadLetterConfigUpdated (139.36s)
--- PASS: TestAccAWSLambdaFunction_disablePublish (290.84s)
--- PASS: TestAccAWSLambdaFunction_disappears (76.76s)
--- PASS: TestAccAWSLambdaFunction_EmptyVpcConfig (303.87s)
--- PASS: TestAccAWSLambdaFunction_enablePublish (301.82s)
--- PASS: TestAccAWSLambdaFunction_encryptedEnvVariables (152.33s)
--- PASS: TestAccAWSLambdaFunction_Environment_Variables_NoValue (59.03s)
--- PASS: TestAccAWSLambdaFunction_envVariables (135.67s)
--- PASS: TestAccAWSLambdaFunction_expectFilenameAndS3Attributes (19.70s)
--- PASS: TestAccAWSLambdaFunction_FileSystemConfig (2369.47s)
--- PASS: TestAccAWSLambdaFunction_KmsKeyArn_NoEnvironmentVariables (1001.01s)
--- PASS: TestAccAWSLambdaFunction_Layers (830.27s)
--- PASS: TestAccAWSLambdaFunction_LayersUpdate (1218.31s)
--- PASS: TestAccAWSLambdaFunction_localUpdate (1253.77s)
--- PASS: TestAccAWSLambdaFunction_localUpdate_nameOnly (318.24s)
--- PASS: TestAccAWSLambdaFunction_nilDeadLetterConfig (75.02s)
--- PASS: TestAccAWSLambdaFunction_runtimes (434.13s)
--- PASS: TestAccAWSLambdaFunction_s3 (39.17s)
--- PASS: TestAccAWSLambdaFunction_s3Update_basic (65.26s)
--- PASS: TestAccAWSLambdaFunction_s3Update_unversioned (66.94s)
--- PASS: TestAccAWSLambdaFunction_tags (111.80s)
--- PASS: TestAccAWSLambdaFunction_tracingConfig (1022.97s)
--- PASS: TestAccAWSLambdaFunction_UnpublishedCodeUpdate (326.86s)
--- PASS: TestAccAWSLambdaFunction_versioned (816.85s)
--- PASS: TestAccAWSLambdaFunction_versionedUpdate (1283.13s)
--- PASS: TestAccAWSLambdaFunction_VPC (810.42s)
--- PASS: TestAccAWSLambdaFunction_VPC_withInvocation (1415.48s)
--- PASS: TestAccAWSLambdaFunction_VpcConfig_ProperIamDependencies (346.28s)
--- PASS: TestAccAWSLambdaFunction_VPCRemoval (2383.24s)
--- PASS: TestAccAWSLambdaFunction_VPCUpdate (2409.76s)
```
  • Loading branch information
bflad authored Jan 20, 2021
1 parent ee57dc3 commit 03757c1
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 18 deletions.
14 changes: 14 additions & 0 deletions aws/resource_aws_lambda_function.go
Original file line number Diff line number Diff line change
Expand Up @@ -1274,6 +1274,20 @@ func waitForLambdaFunctionUpdate(conn *lambda.Lambda, functionName string, timeo
return err
}

func flattenLambdaEnvironment(apiObject *lambda.EnvironmentResponse) []interface{} {
if apiObject == nil {
return nil
}

tfMap := map[string]interface{}{}

if v := apiObject.Variables; v != nil {
tfMap["variables"] = aws.StringValueMap(v)
}

return []interface{}{tfMap}
}

func flattenLambdaFileSystemConfigs(fscList []*lambda.FileSystemConfig) []map[string]interface{} {
results := make([]map[string]interface{}, 0, len(fscList))
for _, fsc := range fscList {
Expand Down
47 changes: 47 additions & 0 deletions aws/resource_aws_lambda_function_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -416,6 +416,33 @@ func TestAccAWSLambdaFunction_envVariables(t *testing.T) {
})
}

func TestAccAWSLambdaFunction_Environment_Variables_NoValue(t *testing.T) {
var conf lambda.GetFunctionOutput
rName := acctest.RandomWithPrefix("tf-acc-test")
resourceName := "aws_lambda_function.test"

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckLambdaFunctionDestroy,
Steps: []resource.TestStep{
{
Config: testAccAWSLambdaConfigEnvironmentVariablesNoValue(rName),
Check: resource.ComposeTestCheckFunc(
testAccCheckAwsLambdaFunctionExists(resourceName, rName, &conf),
resource.TestCheckResourceAttr(resourceName, "environment.0.variables.key1", ""),
),
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"filename", "publish"},
},
},
})
}

func TestAccAWSLambdaFunction_encryptedEnvVariables(t *testing.T) {
var conf lambda.GetFunctionOutput

Expand Down Expand Up @@ -2241,6 +2268,26 @@ resource "aws_lambda_function" "test" {
`, funcName)
}

func testAccAWSLambdaConfigEnvironmentVariablesNoValue(rName string) string {
return composeConfig(
baseAccAWSLambdaConfig(rName, rName, rName),
fmt.Sprintf(`
resource "aws_lambda_function" "test" {
filename = "test-fixtures/lambdatest.zip"
function_name = %[1]q
handler = "exports.example"
role = aws_iam_role.iam_for_lambda.arn
runtime = "nodejs12.x"
environment {
variables = {
key1 = ""
}
}
}
`, rName))
}

func testAccAWSLambdaConfigEncryptedEnvVariables(keyDesc, funcName, policyName, roleName, sgName string) string {
return fmt.Sprintf(baseAccAWSLambdaConfig(policyName, roleName, sgName)+`
resource "aws_kms_key" "foo" {
Expand Down
18 changes: 0 additions & 18 deletions aws/structure.go
Original file line number Diff line number Diff line change
Expand Up @@ -1587,24 +1587,6 @@ func flattenDSVpcSettings(
return []map[string]interface{}{settings}
}

func flattenLambdaEnvironment(lambdaEnv *lambda.EnvironmentResponse) []interface{} {
envs := make(map[string]interface{})
en := make(map[string]string)

if lambdaEnv == nil {
return nil
}

for k, v := range lambdaEnv.Variables {
en[k] = *v
}
if len(en) > 0 {
envs["variables"] = en
}

return []interface{}{envs}
}

func expandLambdaEventSourceMappingDestinationConfig(vDest []interface{}) *lambda.DestinationConfig {
if len(vDest) == 0 {
return nil
Expand Down

0 comments on commit 03757c1

Please sign in to comment.