diff --git a/aws/resource_aws_lambda_alias.go b/aws/resource_aws_lambda_alias.go index 84510e5b709..09d2416a4e9 100644 --- a/aws/resource_aws_lambda_alias.go +++ b/aws/resource_aws_lambda_alias.go @@ -1,6 +1,7 @@ package aws import ( + "errors" "fmt" "log" "strings" @@ -19,27 +20,41 @@ func resourceAwsLambdaAlias() *schema.Resource { Delete: resourceAwsLambdaAliasDelete, Schema: map[string]*schema.Schema{ - "description": &schema.Schema{ + "description": { Type: schema.TypeString, Optional: true, }, - "function_name": &schema.Schema{ + "function_name": { Type: schema.TypeString, Required: true, }, - "function_version": &schema.Schema{ + "function_version": { Type: schema.TypeString, Required: true, }, - "name": &schema.Schema{ + "name": { Type: schema.TypeString, Required: true, ForceNew: true, }, - "arn": &schema.Schema{ + "arn": { Type: schema.TypeString, Computed: true, }, + "routing_config": { + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "additional_version_weights": { + Type: schema.TypeMap, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeFloat}, + }, + }, + }, + }, }, } } @@ -61,6 +76,10 @@ func resourceAwsLambdaAliasCreate(d *schema.ResourceData, meta interface{}) erro Name: aws.String(aliasName), } + if v, ok := d.GetOk("routing_config"); ok { + params.RoutingConfig = expandLambdaAliasRoutingConfiguration(v.([]interface{})) + } + aliasConfiguration, err := conn.CreateAlias(params) if err != nil { return fmt.Errorf("Error creating Lambda alias: %s", err) @@ -99,6 +118,10 @@ func resourceAwsLambdaAliasRead(d *schema.ResourceData, meta interface{}) error d.Set("name", aliasConfiguration.Name) d.Set("arn", aliasConfiguration.AliasArn) + if err := d.Set("routing_config", flattenLambdaAliasRoutingConfiguration(aliasConfiguration.RoutingConfig)); err != nil { + return fmt.Errorf("error setting routing_config: %s", err) + } + return nil } @@ -134,6 +157,20 @@ func resourceAwsLambdaAliasUpdate(d *schema.ResourceData, meta interface{}) erro FunctionName: aws.String(d.Get("function_name").(string)), FunctionVersion: aws.String(d.Get("function_version").(string)), Name: aws.String(d.Get("name").(string)), + RoutingConfig: &lambda.AliasRoutingConfiguration{}, + } + + if v, ok := d.GetOk("routing_config"); ok { + routingConfigs := v.([]interface{}) + routingConfig, ok := routingConfigs[0].(map[string]interface{}) + if !ok { + return errors.New("At least one field is expected inside routing_config") + } + + if additionalVersionWeights, ok := routingConfig["additional_version_weights"]; ok { + weights := readAdditionalVersionWeights(additionalVersionWeights.(map[string]interface{})) + params.RoutingConfig.AdditionalVersionWeights = aws.Float64Map(weights) + } } _, err := conn.UpdateAlias(params) @@ -143,3 +180,28 @@ func resourceAwsLambdaAliasUpdate(d *schema.ResourceData, meta interface{}) erro return nil } + +func expandLambdaAliasRoutingConfiguration(l []interface{}) *lambda.AliasRoutingConfiguration { + aliasRoutingConfiguration := &lambda.AliasRoutingConfiguration{} + + if len(l) == 0 || l[0] == nil { + return aliasRoutingConfiguration + } + + m := l[0].(map[string]interface{}) + + if _, ok := m["additional_version_weights"]; ok { + aliasRoutingConfiguration.AdditionalVersionWeights = expandFloat64Map(m) + } + + return aliasRoutingConfiguration +} + +func readAdditionalVersionWeights(avw map[string]interface{}) map[string]float64 { + weights := make(map[string]float64) + for k, v := range avw { + weights[k] = v.(float64) + } + + return weights +} diff --git a/aws/resource_aws_lambda_alias_test.go b/aws/resource_aws_lambda_alias_test.go index d9770187b29..683bf0b7317 100644 --- a/aws/resource_aws_lambda_alias_test.go +++ b/aws/resource_aws_lambda_alias_test.go @@ -27,7 +27,7 @@ func TestAccAWSLambdaAlias_basic(t *testing.T) { Providers: testAccProviders, CheckDestroy: testAccCheckAwsLambdaAliasDestroy, Steps: []resource.TestStep{ - resource.TestStep{ + { Config: testAccAwsLambdaAliasConfig(roleName, policyName, attachmentName, funcName, aliasName), Check: resource.ComposeTestCheckFunc( testAccCheckAwsLambdaAliasExists("aws_lambda_alias.lambda_alias_test", &conf), @@ -56,7 +56,7 @@ func TestAccAWSLambdaAlias_nameupdate(t *testing.T) { Providers: testAccProviders, CheckDestroy: testAccCheckAwsLambdaAliasDestroy, Steps: []resource.TestStep{ - resource.TestStep{ + { Config: testAccAwsLambdaAliasConfig(roleName, policyName, attachmentName, funcName, aliasName), Check: resource.ComposeTestCheckFunc( testAccCheckAwsLambdaAliasExists("aws_lambda_alias.lambda_alias_test", &conf), @@ -65,7 +65,7 @@ func TestAccAWSLambdaAlias_nameupdate(t *testing.T) { regexp.MustCompile(`^arn:aws:lambda:[a-z]+-[a-z]+-[0-9]+:\d{12}:function:`+funcName+`:`+aliasName+`$`)), ), }, - resource.TestStep{ + { Config: testAccAwsLambdaAliasConfig(roleName, policyName, attachmentName, funcName, aliasNameUpdate), Check: resource.ComposeTestCheckFunc( testAccCheckAwsLambdaAliasExists("aws_lambda_alias.lambda_alias_test", &conf), @@ -142,6 +142,31 @@ func testAccCheckAwsLambdaAttributes(mapping *lambda.AliasConfiguration) resourc } } +func testAccCheckAwsLambdaAliasRoutingConfigExists(mapping *lambda.AliasConfiguration) resource.TestCheckFunc { + return func(s *terraform.State) error { + routingConfig := mapping.RoutingConfig + + if routingConfig == nil { + return fmt.Errorf("Could not read Lambda alias routing config") + } + if len(routingConfig.AdditionalVersionWeights) != 1 { + return fmt.Errorf("Could not read Lambda alias additional version weights") + } + return nil + } +} + +func testAccCheckAwsLambdaAliasRoutingConfigDoesNotExist(mapping *lambda.AliasConfiguration) resource.TestCheckFunc { + return func(s *terraform.State) error { + routingConfig := mapping.RoutingConfig + + if routingConfig != nil { + return fmt.Errorf("Lambda alias routing config still exists after removal") + } + return nil + } +} + func testAccAwsLambdaAliasConfig(roleName, policyName, attachmentName, funcName, aliasName string) string { return fmt.Sprintf(` resource "aws_iam_role" "iam_for_lambda" { @@ -192,17 +217,91 @@ resource "aws_iam_policy_attachment" "policy_attachment_for_role" { } resource "aws_lambda_function" "lambda_function_test_create" { - filename = "test-fixtures/lambdatest.zip" - function_name = "%s" - role = "${aws_iam_role.iam_for_lambda.arn}" - handler = "exports.example" - runtime = "nodejs4.3" + filename = "test-fixtures/lambdatest.zip" + function_name = "%s" + role = "${aws_iam_role.iam_for_lambda.arn}" + handler = "exports.example" + runtime = "nodejs4.3" + source_code_hash = "${base64sha256(file("test-fixtures/lambdatest.zip"))}" + publish = "true" +} + +resource "aws_lambda_alias" "lambda_alias_test" { + name = "%s" + description = "a sample description" + function_name = "${aws_lambda_function.lambda_function_test_create.arn}" + function_version = "1" +}`, roleName, policyName, attachmentName, funcName, aliasName) +} + +func testAccAwsLambdaAliasConfigWithRoutingConfig(roleName, policyName, attachmentName, funcName, aliasName string) string { + return fmt.Sprintf(` +resource "aws_iam_role" "iam_for_lambda" { + name = "%s" + + assume_role_policy = <