From 783fd65e8678d6c84298cba8e11cb0b22501f9e1 Mon Sep 17 00:00:00 2001 From: Joshua Spence Date: Fri, 4 Aug 2017 11:26:26 +1000 Subject: [PATCH] Ignore the VPC configuration for a Lambda function if it is empty I have a `lambda_function` module, which supports both EC2 classic and VPC. The problem I have, however, is that there is no way to specify a null configuration for `vpc_config`. This pull request changes the behavior so that the following Terraform configuration is //ignored//, instead of failing with an error (the current behavior): ``` resource "aws_lambda_function" "test" { # ... vpc_config { security_group_ids = [] subnet_ids = [] } } ``` See also #1187 and #1190. --- aws/resource_aws_lambda_function.go | 26 ++++++++++++++- aws/resource_aws_lambda_function_test.go | 41 ++++++++++++++++++++++++ 2 files changed, 66 insertions(+), 1 deletion(-) diff --git a/aws/resource_aws_lambda_function.go b/aws/resource_aws_lambda_function.go index 8144b2aedb2..479d741c1fe 100644 --- a/aws/resource_aws_lambda_function.go +++ b/aws/resource_aws_lambda_function.go @@ -153,6 +153,31 @@ func resourceAwsLambdaFunction() *schema.Resource { }, }, }, + + // Suppress diffs if the VPC configuration is empty. + DiffSuppressFunc: func(k, old, new string, d *schema.ResourceData) bool { + if v, ok := d.GetOk("vpc_config"); ok { + configs := v.([]interface{}) + config, ok := configs[0].(map[string]interface{}) + + if !ok { + return true + } + + if config == nil { + return true + } + + securityGroups := config["security_group_ids"].(*schema.Set) + subnets := config["subnet_ids"].(*schema.Set) + + if securityGroups.Len() == 0 && subnets.Len() == 0 { + return true + } + } + + return false + }, }, "arn": { Type: schema.TypeString, @@ -306,7 +331,6 @@ func resourceAwsLambdaFunctionCreate(d *schema.ResourceData, meta interface{}) e } if v, ok := d.GetOk("vpc_config"); ok { - configs := v.([]interface{}) config, ok := configs[0].(map[string]interface{}) diff --git a/aws/resource_aws_lambda_function_test.go b/aws/resource_aws_lambda_function_test.go index c1ddb8340f6..11b4fa2a348 100644 --- a/aws/resource_aws_lambda_function_test.go +++ b/aws/resource_aws_lambda_function_test.go @@ -604,6 +604,31 @@ func TestAccAWSLambdaFunction_VPC_withInvocation(t *testing.T) { }) } +func TestAccAWSLambdaFunction_EmptyVpcConfig(t *testing.T) { + var conf lambda.GetFunctionOutput + + rString := acctest.RandString(8) + funcName := fmt.Sprintf("tf_acc_lambda_func_empty_vpc_%s", rString) + policyName := fmt.Sprintf("tf_acc_policy_lambda_func_empty_vpc_%s", rString) + roleName := fmt.Sprintf("tf_acc_role_lambda_func_empty_vpc_%s", rString) + sgName := fmt.Sprintf("tf_acc_sg_lambda_func_empty_vpc_%s", rString) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckLambdaFunctionDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSLambdaConfigWithEmptyVpcConfig(funcName, policyName, roleName, sgName), + Check: resource.ComposeTestCheckFunc( + testAccCheckAwsLambdaFunctionExists("aws_lambda_function.lambda_function_test", funcName, &conf), + resource.TestCheckResourceAttr("aws_lambda_function.lambda_function_test", "vpc_config.#", "0"), + ), + }, + }, + }) +} + func TestAccAWSLambdaFunction_s3(t *testing.T) { var conf lambda.GetFunctionOutput @@ -1688,6 +1713,22 @@ resource "aws_security_group" "sg_for_lambda_2" { `, funcName, sgName2) } +func testAccAWSLambdaConfigWithEmptyVpcConfig(functionName, policyName, roleName, sgName string) string { + return fmt.Sprintf(baseAccAWSLambdaConfig(policyName, roleName, sgName)+` +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" + + vpc_config { + subnet_ids = [] + security_group_ids = [] + } +}`, functionName) +} + func testAccAWSLambdaConfigS3(bucketName, roleName, funcName string) string { return fmt.Sprintf(` resource "aws_s3_bucket" "lambda_bucket" {