VPC config support in Lambda functions

fixes #5105
This commit is contained in:
vince rosso 2016-02-15 21:38:17 -08:00 committed by vince rosso
parent 97af014d81
commit 3baabb0186
3 changed files with 134 additions and 0 deletions

View File

@ -83,6 +83,29 @@ func resourceAwsLambdaFunction() *schema.Resource {
Default: 3,
ForceNew: true, // TODO make this editable
},
"vpc_config": &schema.Schema{
Type: schema.TypeList,
Optional: true,
ForceNew: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"subnet_ids": &schema.Schema{
Type: schema.TypeSet,
Required: true,
ForceNew: true,
Elem: &schema.Schema{Type: schema.TypeString},
Set: schema.HashString,
},
"security_group_ids": &schema.Schema{
Type: schema.TypeSet,
Required: true,
ForceNew: true,
Elem: &schema.Schema{Type: schema.TypeString},
Set: schema.HashString,
},
},
},
},
"arn": &schema.Schema{
Type: schema.TypeString,
Computed: true,
@ -149,6 +172,31 @@ func resourceAwsLambdaFunctionCreate(d *schema.ResourceData, meta interface{}) e
Timeout: aws.Int64(int64(d.Get("timeout").(int))),
}
if v, ok := d.GetOk("vpc_config"); ok {
configs := v.([]interface{})
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
for _, id := range config["subnet_ids"].(*schema.Set).List() {
subnetIds = append(subnetIds, aws.String(id.(string)))
}
var securityGroupIds []*string
for _, id := range config["security_group_ids"].(*schema.Set).List() {
securityGroupIds = append(securityGroupIds, aws.String(id.(string)))
}
var vpcConfig = &lambda.VpcConfig{
SubnetIds: subnetIds,
SecurityGroupIds: securityGroupIds,
}
params.VpcConfig = vpcConfig
}
}
// IAM profiles can take ~10 seconds to propagate in AWS:
// http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/iam-roles-for-amazon-ec2.html#launch-instance-with-role-console
// Error creating Lambda function: InvalidParameterValueException: The role defined for the task cannot be assumed by Lambda.
@ -157,10 +205,12 @@ func resourceAwsLambdaFunctionCreate(d *schema.ResourceData, meta interface{}) e
if err != nil {
if awserr, ok := err.(awserr.Error); ok {
if awserr.Code() == "InvalidParameterValueException" {
log.Printf("[DEBUG] InvalidParameterValueException creating Lambda Function: %s", awserr)
// Retryable
return awserr
}
}
log.Printf("[DEBUG] Error creating Lambda Function: %s", err)
// Not retryable
return resource.RetryError{Err: err}
}
@ -207,6 +257,7 @@ func resourceAwsLambdaFunctionRead(d *schema.ResourceData, meta interface{}) err
d.Set("role", function.Role)
d.Set("runtime", function.Runtime)
d.Set("timeout", function.Timeout)
d.Set("vpc_config", flattenLambdaVpcConfigResponse(function.VpcConfig))
return nil
}

View File

@ -97,6 +97,36 @@ func testAccCheckAWSLambdaAttributes(function *lambda.GetFunctionOutput) resourc
}
const testAccAWSLambdaConfig = `
resource "aws_iam_role_policy" "iam_policy_for_lambda" {
name = "iam_policy_for_lambda"
role = "${aws_iam_role.iam_for_lambda.id}"
policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource": "arn:aws:logs:*:*:*"
},
{
"Effect": "Allow",
"Action": [
"ec2:CreateNetworkInterface"
],
"Resource": [
"*"
]
}
]
}
EOF
}
resource "aws_iam_role" "iam_for_lambda" {
name = "iam_for_lambda"
assume_role_policy = <<EOF
@ -116,10 +146,48 @@ resource "aws_iam_role" "iam_for_lambda" {
EOF
}
resource "aws_vpc" "vpc_for_lambda" {
cidr_block = "10.0.0.0/16"
}
resource "aws_subnet" "subnet_for_lambda" {
vpc_id = "${aws_vpc.vpc_for_lambda.id}"
cidr_block = "10.0.1.0/24"
tags {
Name = "lambda"
}
}
resource "aws_security_group" "sg_for_lambda" {
name = "sg_for_lambda"
description = "Allow all inbound traffic for lambda test"
vpc_id = "${aws_vpc.vpc_for_lambda.id}"
ingress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
}
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"
vpc_config = {
subnet_ids = ["${aws_subnet.subnet_for_lambda.id}"]
security_group_ids = ["${aws_security_group.sg_for_lambda.id}"]
}
}
`

View File

@ -15,6 +15,7 @@ import (
"github.com/aws/aws-sdk-go/service/elasticache"
elasticsearch "github.com/aws/aws-sdk-go/service/elasticsearchservice"
"github.com/aws/aws-sdk-go/service/elb"
"github.com/aws/aws-sdk-go/service/lambda"
"github.com/aws/aws-sdk-go/service/rds"
"github.com/aws/aws-sdk-go/service/redshift"
"github.com/aws/aws-sdk-go/service/route53"
@ -680,6 +681,20 @@ func flattenDSVpcSettings(
return []map[string]interface{}{settings}
}
func flattenLambdaVpcConfigResponse(s *lambda.VpcConfigResponse) []map[string]interface{} {
settings := make(map[string]interface{}, 0)
if s == nil {
return nil
}
settings["subnet_ids"] = schema.NewSet(schema.HashString, flattenStringList(s.SubnetIds))
settings["security_group_ids"] = schema.NewSet(schema.HashString, flattenStringList(s.SecurityGroupIds))
settings["vpc_id"] = *s.VpcId
return []map[string]interface{}{settings}
}
func flattenDSConnectSettings(
customerDnsIps []*string,
s *directoryservice.DirectoryConnectSettingsDescription) []map[string]interface{} {