diff --git a/builtin/providers/aws/resource_aws_alb_listener_rule.go b/builtin/providers/aws/resource_aws_alb_listener_rule.go index d82d7410a..cf33f04c4 100644 --- a/builtin/providers/aws/resource_aws_alb_listener_rule.go +++ b/builtin/providers/aws/resource_aws_alb_listener_rule.go @@ -35,6 +35,7 @@ func resourceAwsAlbListenerRule() *schema.Resource { "priority": { Type: schema.TypeInt, Required: true, + ForceNew: true, ValidateFunc: validateAwsAlbListenerRulePriority, }, "action": { @@ -184,42 +185,75 @@ func resourceAwsAlbListenerRuleRead(d *schema.ResourceData, meta interface{}) er func resourceAwsAlbListenerRuleUpdate(d *schema.ResourceData, meta interface{}) error { elbconn := meta.(*AWSClient).elbv2conn + d.Partial(true) + + if d.HasChange("priority") { + params := &elbv2.SetRulePrioritiesInput{ + RulePriorities: []*elbv2.RulePriorityPair{ + { + RuleArn: aws.String(d.Id()), + Priority: aws.Int64(int64(d.Get("priority").(int))), + }, + }, + } + + _, err := elbconn.SetRulePriorities(params) + if err != nil { + return err + } + + d.SetPartial("priority") + } + + requestUpdate := false params := &elbv2.ModifyRuleInput{ RuleArn: aws.String(d.Id()), } - actions := d.Get("action").([]interface{}) - params.Actions = make([]*elbv2.Action, len(actions)) - for i, action := range actions { - actionMap := action.(map[string]interface{}) - params.Actions[i] = &elbv2.Action{ - TargetGroupArn: aws.String(actionMap["target_group_arn"].(string)), - Type: aws.String(actionMap["type"].(string)), + if d.HasChange("action") { + actions := d.Get("action").([]interface{}) + params.Actions = make([]*elbv2.Action, len(actions)) + for i, action := range actions { + actionMap := action.(map[string]interface{}) + params.Actions[i] = &elbv2.Action{ + TargetGroupArn: aws.String(actionMap["target_group_arn"].(string)), + Type: aws.String(actionMap["type"].(string)), + } + } + requestUpdate = true + d.SetPartial("action") + } + + if d.HasChange("condition") { + conditions := d.Get("condition").([]interface{}) + params.Conditions = make([]*elbv2.RuleCondition, len(conditions)) + for i, condition := range conditions { + conditionMap := condition.(map[string]interface{}) + values := conditionMap["values"].([]interface{}) + params.Conditions[i] = &elbv2.RuleCondition{ + Field: aws.String(conditionMap["field"].(string)), + Values: make([]*string, len(values)), + } + for j, value := range values { + params.Conditions[i].Values[j] = aws.String(value.(string)) + } + } + requestUpdate = true + d.SetPartial("condition") + } + + if requestUpdate { + resp, err := elbconn.ModifyRule(params) + if err != nil { + return errwrap.Wrapf("Error modifying ALB Listener Rule: {{err}}", err) + } + + if len(resp.Rules) == 0 { + return errors.New("Error modifying creating ALB Listener Rule: no rules returned in response") } } - conditions := d.Get("condition").([]interface{}) - params.Conditions = make([]*elbv2.RuleCondition, len(conditions)) - for i, condition := range conditions { - conditionMap := condition.(map[string]interface{}) - values := conditionMap["values"].([]interface{}) - params.Conditions[i] = &elbv2.RuleCondition{ - Field: aws.String(conditionMap["field"].(string)), - Values: make([]*string, len(values)), - } - for j, value := range values { - params.Conditions[i].Values[j] = aws.String(value.(string)) - } - } - - resp, err := elbconn.ModifyRule(params) - if err != nil { - return errwrap.Wrapf("Error modifying ALB Listener Rule: {{err}}", err) - } - - if len(resp.Rules) == 0 { - return errors.New("Error modifying creating ALB Listener Rule: no rules returned in response") - } + d.Partial(false) return resourceAwsAlbListenerRuleRead(d, meta) } diff --git a/builtin/providers/aws/resource_aws_alb_listener_rule_test.go b/builtin/providers/aws/resource_aws_alb_listener_rule_test.go index 0407ca614..86c0d83cb 100644 --- a/builtin/providers/aws/resource_aws_alb_listener_rule_test.go +++ b/builtin/providers/aws/resource_aws_alb_listener_rule_test.go @@ -44,6 +44,35 @@ func TestAccAWSALBListenerRule_basic(t *testing.T) { }) } +func TestAccAWSALBListenerRule_updateRulePriority(t *testing.T) { + var rule elbv2.Rule + albName := fmt.Sprintf("testrule-basic-%s", acctest.RandStringFromCharSet(13, acctest.CharSetAlphaNum)) + targetGroupName := fmt.Sprintf("testtargetgroup-%s", acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + IDRefreshName: "aws_alb_listener_rule.static", + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSALBListenerRuleDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSALBListenerRuleConfig_basic(albName, targetGroupName), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSALBListenerRuleExists("aws_alb_listener_rule.static", &rule), + resource.TestCheckResourceAttr("aws_alb_listener_rule.static", "priority", "100"), + ), + }, + { + Config: testAccAWSALBListenerRuleConfig_updateRulePriority(albName, targetGroupName), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSALBListenerRuleExists("aws_alb_listener_rule.static", &rule), + resource.TestCheckResourceAttr("aws_alb_listener_rule.static", "priority", "101"), + ), + }, + }, + }) +} + func TestAccAWSALBListenerRule_multipleConditionThrowsError(t *testing.T) { albName := fmt.Sprintf("testrule-basic-%s", acctest.RandStringFromCharSet(13, acctest.CharSetAlphaNum)) targetGroupName := fmt.Sprintf("testtargetgroup-%s", acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)) @@ -343,3 +372,115 @@ resource "aws_security_group" "alb_test" { } }`, albName, targetGroupName) } + +func testAccAWSALBListenerRuleConfig_updateRulePriority(albName, targetGroupName string) string { + return fmt.Sprintf(` +resource "aws_alb_listener_rule" "static" { + listener_arn = "${aws_alb_listener.front_end.arn}" + priority = 101 + + action { + type = "forward" + target_group_arn = "${aws_alb_target_group.test.arn}" + } + + condition { + field = "path-pattern" + values = ["/static/*"] + } +} + +resource "aws_alb_listener" "front_end" { + load_balancer_arn = "${aws_alb.alb_test.id}" + protocol = "HTTP" + port = "80" + + default_action { + target_group_arn = "${aws_alb_target_group.test.id}" + type = "forward" + } +} + +resource "aws_alb" "alb_test" { + name = "%s" + internal = true + security_groups = ["${aws_security_group.alb_test.id}"] + subnets = ["${aws_subnet.alb_test.*.id}"] + + idle_timeout = 30 + enable_deletion_protection = false + + tags { + TestName = "TestAccAWSALB_basic" + } +} + +resource "aws_alb_target_group" "test" { + name = "%s" + port = 8080 + protocol = "HTTP" + vpc_id = "${aws_vpc.alb_test.id}" + + health_check { + path = "/health" + interval = 60 + port = 8081 + protocol = "HTTP" + timeout = 3 + healthy_threshold = 3 + unhealthy_threshold = 3 + matcher = "200-299" + } +} + +variable "subnets" { + default = ["10.0.1.0/24", "10.0.2.0/24"] + type = "list" +} + +data "aws_availability_zones" "available" {} + +resource "aws_vpc" "alb_test" { + cidr_block = "10.0.0.0/16" + + tags { + TestName = "TestAccAWSALB_basic" + } +} + +resource "aws_subnet" "alb_test" { + count = 2 + vpc_id = "${aws_vpc.alb_test.id}" + cidr_block = "${element(var.subnets, count.index)}" + map_public_ip_on_launch = true + availability_zone = "${element(data.aws_availability_zones.available.names, count.index)}" + + tags { + TestName = "TestAccAWSALB_basic" + } +} + +resource "aws_security_group" "alb_test" { + name = "allow_all_alb_test" + description = "Used for ALB Testing" + vpc_id = "${aws_vpc.alb_test.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"] + } + + tags { + TestName = "TestAccAWSALB_basic" + } +}`, albName, targetGroupName) +}