Merge pull request #5182 from Originate/mb-fix-lambda-vpc-implementation

provider/aws: Fixes terraform crash when lambda VpcId is nil
This commit is contained in:
James Nugent 2016-02-24 17:52:38 -05:00
commit 74e5711f08
3 changed files with 82 additions and 25 deletions

View File

@ -173,12 +173,11 @@ func resourceAwsLambdaFunctionCreate(d *schema.ResourceData, meta interface{}) e
} }
if v, ok := d.GetOk("vpc_config"); ok { if v, ok := d.GetOk("vpc_config"); ok {
configs := v.([]interface{}) config, err := validateVPCConfig(v)
if err != nil {
return err
}
if len(configs) > 1 {
return errors.New("Only a single vpc_config block is expected")
} else if len(configs) == 1 {
config := configs[0].(map[string]interface{})
var subnetIds []*string var subnetIds []*string
for _, id := range config["subnet_ids"].(*schema.Set).List() { for _, id := range config["subnet_ids"].(*schema.Set).List() {
subnetIds = append(subnetIds, aws.String(id.(string))) subnetIds = append(subnetIds, aws.String(id.(string)))
@ -189,12 +188,10 @@ func resourceAwsLambdaFunctionCreate(d *schema.ResourceData, meta interface{}) e
securityGroupIds = append(securityGroupIds, aws.String(id.(string))) securityGroupIds = append(securityGroupIds, aws.String(id.(string)))
} }
var vpcConfig = &lambda.VpcConfig{ params.VpcConfig = &lambda.VpcConfig{
SubnetIds: subnetIds, SubnetIds: subnetIds,
SecurityGroupIds: securityGroupIds, SecurityGroupIds: securityGroupIds,
} }
params.VpcConfig = vpcConfig
}
} }
// IAM profiles can take ~10 seconds to propagate in AWS: // IAM profiles can take ~10 seconds to propagate in AWS:
@ -257,7 +254,9 @@ func resourceAwsLambdaFunctionRead(d *schema.ResourceData, meta interface{}) err
d.Set("role", function.Role) d.Set("role", function.Role)
d.Set("runtime", function.Runtime) d.Set("runtime", function.Runtime)
d.Set("timeout", function.Timeout) d.Set("timeout", function.Timeout)
d.Set("vpc_config", flattenLambdaVpcConfigResponse(function.VpcConfig)) if config := flattenLambdaVpcConfigResponse(function.VpcConfig); len(config) > 0 {
d.Set("vpc_config", config)
}
return nil return nil
} }
@ -286,7 +285,28 @@ func resourceAwsLambdaFunctionDelete(d *schema.ResourceData, meta interface{}) e
// resourceAwsLambdaFunctionUpdate maps to: // resourceAwsLambdaFunctionUpdate maps to:
// UpdateFunctionCode in the API / SDK // UpdateFunctionCode in the API / SDK
func resourceAwsLambdaFunctionUpdate(d *schema.ResourceData, meta interface{}) error { func resourceAwsLambdaFunctionUpdate(d *schema.ResourceData, meta interface{}) error {
// conn := meta.(*AWSClient).lambdaconn
return nil return nil
} }
func validateVPCConfig(v interface{}) (map[string]interface{}, error) {
configs := v.([]interface{})
if len(configs) > 1 {
return nil, errors.New("Only a single vpc_config block is expected")
}
config, ok := configs[0].(map[string]interface{})
if !ok {
return nil, errors.New("vpc_config is <nil>")
}
if config["subnet_ids"].(*schema.Set).Len() == 0 {
return nil, errors.New("vpc_config.subnet_ids cannot be empty")
}
if config["security_group_ids"].(*schema.Set).Len() == 0 {
return nil, errors.New("vpc_config.security_group_ids cannot be empty")
}
return config, nil
}

View File

@ -19,7 +19,26 @@ func TestAccAWSLambdaFunction_basic(t *testing.T) {
CheckDestroy: testAccCheckLambdaFunctionDestroy, CheckDestroy: testAccCheckLambdaFunctionDestroy,
Steps: []resource.TestStep{ Steps: []resource.TestStep{
resource.TestStep{ resource.TestStep{
Config: testAccAWSLambdaConfig, Config: testAccAWSLambdaConfigBasic,
Check: resource.ComposeTestCheckFunc(
testAccCheckAwsLambdaFunctionExists("aws_lambda_function.lambda_function_test", &conf),
testAccCheckAWSLambdaAttributes(&conf),
),
},
},
})
}
func TestAccAWSLambdaFunction_VPC(t *testing.T) {
var conf lambda.GetFunctionOutput
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckLambdaFunctionDestroy,
Steps: []resource.TestStep{
resource.TestStep{
Config: testAccAWSLambdaConfigWithVPC,
Check: resource.ComposeTestCheckFunc( Check: resource.ComposeTestCheckFunc(
testAccCheckAwsLambdaFunctionExists("aws_lambda_function.lambda_function_test", &conf), testAccCheckAwsLambdaFunctionExists("aws_lambda_function.lambda_function_test", &conf),
testAccCheckAWSLambdaAttributes(&conf), testAccCheckAWSLambdaAttributes(&conf),
@ -96,7 +115,7 @@ func testAccCheckAWSLambdaAttributes(function *lambda.GetFunctionOutput) resourc
} }
} }
const testAccAWSLambdaConfig = ` const baseAccAWSLambdaConfig = `
resource "aws_iam_role_policy" "iam_policy_for_lambda" { resource "aws_iam_role_policy" "iam_policy_for_lambda" {
name = "iam_policy_for_lambda" name = "iam_policy_for_lambda"
role = "${aws_iam_role.iam_for_lambda.id}" role = "${aws_iam_role.iam_for_lambda.id}"
@ -179,6 +198,18 @@ resource "aws_security_group" "sg_for_lambda" {
} }
} }
`
const testAccAWSLambdaConfigBasic = baseAccAWSLambdaConfig + `
resource "aws_lambda_function" "lambda_function_test" {
filename = "test-fixtures/lambdatest.zip"
function_name = "example_lambda_name"
role = "${aws_iam_role.iam_for_lambda.arn}"
handler = "exports.example"
}
`
const testAccAWSLambdaConfigWithVPC = baseAccAWSLambdaConfig + `
resource "aws_lambda_function" "lambda_function_test" { resource "aws_lambda_function" "lambda_function_test" {
filename = "test-fixtures/lambdatest.zip" filename = "test-fixtures/lambdatest.zip"
function_name = "example_lambda_name" function_name = "example_lambda_name"

View File

@ -688,9 +688,15 @@ func flattenLambdaVpcConfigResponse(s *lambda.VpcConfigResponse) []map[string]in
return nil return nil
} }
if len(s.SubnetIds) == 0 && len(s.SecurityGroupIds) == 0 && s.VpcId == nil {
return nil
}
settings["subnet_ids"] = schema.NewSet(schema.HashString, flattenStringList(s.SubnetIds)) settings["subnet_ids"] = schema.NewSet(schema.HashString, flattenStringList(s.SubnetIds))
settings["security_group_ids"] = schema.NewSet(schema.HashString, flattenStringList(s.SecurityGroupIds)) settings["security_group_ids"] = schema.NewSet(schema.HashString, flattenStringList(s.SecurityGroupIds))
if s.VpcId != nil {
settings["vpc_id"] = *s.VpcId settings["vpc_id"] = *s.VpcId
}
return []map[string]interface{}{settings} return []map[string]interface{}{settings}
} }