Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

provider/aws: Support ip_address_type for aws_alb #13227

Merged
merged 1 commit into from
Apr 4, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 55 additions & 2 deletions builtin/providers/aws/resource_aws_alb.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,12 @@ func resourceAwsAlb() *schema.Resource {
Default: 60,
},

"ip_address_type": {
Type: schema.TypeString,
Computed: true,
Optional: true,
},

"vpc_id": {
Type: schema.TypeString,
Computed: true,
Expand Down Expand Up @@ -158,6 +164,10 @@ func resourceAwsAlbCreate(d *schema.ResourceData, meta interface{}) error {
elbOpts.Subnets = expandStringList(v.(*schema.Set).List())
}

if v, ok := d.GetOk("ip_address_type"); ok {
elbOpts.IpAddressType = aws.String(v.(string))
}

log.Printf("[DEBUG] ALB create configuration: %#v", elbOpts)

resp, err := elbconn.CreateLoadBalancer(elbOpts)
Expand All @@ -174,7 +184,7 @@ func resourceAwsAlbCreate(d *schema.ResourceData, meta interface{}) error {
log.Printf("[INFO] ALB ID: %s", d.Id())

stateConf := &resource.StateChangeConf{
Pending: []string{"active", "provisioning", "failed"},
Pending: []string{"provisioning", "failed"},
Target: []string{"active"},
Refresh: func() (interface{}, string, error) {
describeResp, err := elbconn.DescribeLoadBalancers(&elbv2.DescribeLoadBalancersInput{
Expand All @@ -193,7 +203,7 @@ func resourceAwsAlbCreate(d *schema.ResourceData, meta interface{}) error {

return describeResp, *dLb.State.Code, nil
},
Timeout: 5 * time.Minute,
Timeout: 10 * time.Minute,
MinTimeout: 3 * time.Second,
}
_, err = stateConf.WaitForState()
Expand Down Expand Up @@ -325,6 +335,48 @@ func resourceAwsAlbUpdate(d *schema.ResourceData, meta interface{}) error {
}
}

if d.HasChange("ip_address_type") {

params := &elbv2.SetIpAddressTypeInput{
LoadBalancerArn: aws.String(d.Id()),
IpAddressType: aws.String(d.Get("ip_address_type").(string)),
}

_, err := elbconn.SetIpAddressType(params)
if err != nil {
return fmt.Errorf("Failure Setting ALB IP Address Type: %s", err)
}

}

stateConf := &resource.StateChangeConf{
Pending: []string{"active", "provisioning", "failed"},
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is a typo - active shouldn't be treated as Pending?

Target: []string{"active"},
Refresh: func() (interface{}, string, error) {
describeResp, err := elbconn.DescribeLoadBalancers(&elbv2.DescribeLoadBalancersInput{
LoadBalancerArns: []*string{aws.String(d.Id())},
})
if err != nil {
return nil, "", err
}

if len(describeResp.LoadBalancers) != 1 {
return nil, "", fmt.Errorf("No load balancers returned for %s", d.Id())
}
dLb := describeResp.LoadBalancers[0]

log.Printf("[INFO] ALB state: %s", *dLb.State.Code)

return describeResp, *dLb.State.Code, nil
},
Timeout: 10 * time.Minute,
MinTimeout: 3 * time.Second,
}
_, err := stateConf.WaitForState()
if err != nil {
return err
}

return resourceAwsAlbRead(d, meta)
}

Expand Down Expand Up @@ -381,6 +433,7 @@ func flattenAwsAlbResource(d *schema.ResourceData, meta interface{}, alb *elbv2.
d.Set("vpc_id", alb.VpcId)
d.Set("zone_id", alb.CanonicalHostedZoneId)
d.Set("dns_name", alb.DNSName)
d.Set("ip_address_type", alb.IpAddressType)

respTags, err := elbconn.DescribeTags(&elbv2.DescribeTagsInput{
ResourceArns: []*string{alb.LoadBalancerArn},
Expand Down
251 changes: 251 additions & 0 deletions builtin/providers/aws/resource_aws_alb_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ func TestAccAWSALB_basic(t *testing.T) {
resource.TestCheckResourceAttr("aws_alb.alb_test", "tags.TestName", "TestAccAWSALB_basic"),
resource.TestCheckResourceAttr("aws_alb.alb_test", "enable_deletion_protection", "false"),
resource.TestCheckResourceAttr("aws_alb.alb_test", "idle_timeout", "30"),
resource.TestCheckResourceAttr("aws_alb.alb_test", "ip_address_type", "ipv4"),
resource.TestCheckResourceAttrSet("aws_alb.alb_test", "vpc_id"),
resource.TestCheckResourceAttrSet("aws_alb.alb_test", "zone_id"),
resource.TestCheckResourceAttrSet("aws_alb.alb_test", "dns_name"),
Expand Down Expand Up @@ -208,6 +209,34 @@ func TestAccAWSALB_updatedSubnets(t *testing.T) {
})
}

func TestAccAWSALB_updatedIpAddressType(t *testing.T) {
var pre, post elbv2.LoadBalancer
albName := fmt.Sprintf("testaccawsalb-basic-%s", acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum))

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
IDRefreshName: "aws_alb.alb_test",
Providers: testAccProviders,
CheckDestroy: testAccCheckAWSALBDestroy,
Steps: []resource.TestStep{
{
Config: testAccAWSALBConfigWithIpAddressType(albName),
Check: resource.ComposeAggregateTestCheckFunc(
testAccCheckAWSALBExists("aws_alb.alb_test", &pre),
resource.TestCheckResourceAttr("aws_alb.alb_test", "ip_address_type", "ipv4"),
),
},
{
Config: testAccAWSALBConfigWithIpAddressTypeUpdated(albName),
Check: resource.ComposeAggregateTestCheckFunc(
testAccCheckAWSALBExists("aws_alb.alb_test", &post),
resource.TestCheckResourceAttr("aws_alb.alb_test", "ip_address_type", "dualstack"),
),
},
},
})
}

// TestAccAWSALB_noSecurityGroup regression tests the issue in #8264,
// where if an ALB is created without a security group, a default one
// is assigned.
Expand Down Expand Up @@ -388,6 +417,228 @@ func testAccCheckAWSALBDestroy(s *terraform.State) error {
return nil
}

func testAccAWSALBConfigWithIpAddressTypeUpdated(albName string) string {
return fmt.Sprintf(`resource "aws_alb" "alb_test" {
name = "%s"
security_groups = ["${aws_security_group.alb_test.id}"]
subnets = ["${aws_subnet.alb_test_1.id}", "${aws_subnet.alb_test_2.id}"]

ip_address_type = "dualstack"

idle_timeout = 30
enable_deletion_protection = false

tags {
TestName = "TestAccAWSALB_basic"
}
}

resource "aws_alb_listener" "test" {
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_target_group" "test" {
name = "%s"
port = 80
protocol = "HTTP"
vpc_id = "${aws_vpc.alb_test.id}"

deregistration_delay = 200

stickiness {
type = "lb_cookie"
cookie_duration = 10000
}

health_check {
path = "/health2"
interval = 30
port = 8082
protocol = "HTTPS"
timeout = 4
healthy_threshold = 4
unhealthy_threshold = 4
matcher = "200"
}
}

resource "aws_egress_only_internet_gateway" "igw" {
vpc_id = "${aws_vpc.alb_test.id}"
}

resource "aws_vpc" "alb_test" {
cidr_block = "10.0.0.0/16"
assign_generated_ipv6_cidr_block = true

tags {
TestName = "TestAccAWSALB_basic"
}
}

resource "aws_internet_gateway" "foo" {
vpc_id = "${aws_vpc.alb_test.id}"
}

resource "aws_subnet" "alb_test_1" {
vpc_id = "${aws_vpc.alb_test.id}"
cidr_block = "10.0.1.0/24"
map_public_ip_on_launch = true
availability_zone = "us-west-2a"
ipv6_cidr_block = "${cidrsubnet(aws_vpc.alb_test.ipv6_cidr_block, 8, 1)}"

tags {
TestName = "TestAccAWSALB_basic"
}
}

resource "aws_subnet" "alb_test_2" {
vpc_id = "${aws_vpc.alb_test.id}"
cidr_block = "10.0.2.0/24"
map_public_ip_on_launch = true
availability_zone = "us-west-2b"
ipv6_cidr_block = "${cidrsubnet(aws_vpc.alb_test.ipv6_cidr_block, 8, 2)}"

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"]
}

tags {
TestName = "TestAccAWSALB_basic"
}
}`, albName, albName)
}

func testAccAWSALBConfigWithIpAddressType(albName string) string {
return fmt.Sprintf(`resource "aws_alb" "alb_test" {
name = "%s"
security_groups = ["${aws_security_group.alb_test.id}"]
subnets = ["${aws_subnet.alb_test_1.id}", "${aws_subnet.alb_test_2.id}"]

ip_address_type = "ipv4"

idle_timeout = 30
enable_deletion_protection = false

tags {
TestName = "TestAccAWSALB_basic"
}
}

resource "aws_alb_listener" "test" {
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_target_group" "test" {
name = "%s"
port = 80
protocol = "HTTP"
vpc_id = "${aws_vpc.alb_test.id}"

deregistration_delay = 200

stickiness {
type = "lb_cookie"
cookie_duration = 10000
}

health_check {
path = "/health2"
interval = 30
port = 8082
protocol = "HTTPS"
timeout = 4
healthy_threshold = 4
unhealthy_threshold = 4
matcher = "200"
}
}

resource "aws_egress_only_internet_gateway" "igw" {
vpc_id = "${aws_vpc.alb_test.id}"
}

resource "aws_vpc" "alb_test" {
cidr_block = "10.0.0.0/16"
assign_generated_ipv6_cidr_block = true

tags {
TestName = "TestAccAWSALB_basic"
}
}

resource "aws_internet_gateway" "foo" {
vpc_id = "${aws_vpc.alb_test.id}"
}

resource "aws_subnet" "alb_test_1" {
vpc_id = "${aws_vpc.alb_test.id}"
cidr_block = "10.0.1.0/24"
map_public_ip_on_launch = true
availability_zone = "us-west-2a"
ipv6_cidr_block = "${cidrsubnet(aws_vpc.alb_test.ipv6_cidr_block, 8, 1)}"

tags {
TestName = "TestAccAWSALB_basic"
}
}

resource "aws_subnet" "alb_test_2" {
vpc_id = "${aws_vpc.alb_test.id}"
cidr_block = "10.0.2.0/24"
map_public_ip_on_launch = true
availability_zone = "us-west-2b"
ipv6_cidr_block = "${cidrsubnet(aws_vpc.alb_test.ipv6_cidr_block, 8, 2)}"

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"]
}

tags {
TestName = "TestAccAWSALB_basic"
}
}`, albName, albName)
}

func testAccAWSALBConfig_basic(albName string) string {
return fmt.Sprintf(`resource "aws_alb" "alb_test" {
name = "%s"
Expand Down
3 changes: 3 additions & 0 deletions website/source/docs/providers/aws/r/alb.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,11 @@ Terraform will autogenerate a name beginning with `tf-lb`.
* `idle_timeout` - (Optional) The time in seconds that the connection is allowed to be idle. Default: 60.
* `enable_deletion_protection` - (Optional) If true, deletion of the load balancer will be disabled via
the AWS API. This will prevent Terraform from deleting the load balancer. Defaults to `false`.
* `ip_address_type` - (Optional) The type of IP addresses used by the subnets for your load balancer. The possible values are `ipv4` and `dualstack`
* `tags` - (Optional) A mapping of tags to assign to the resource.

~> **NOTE::** Please note that internal ALBs can only use `ipv4` as the ip_address_type. You can only change to `dualstack` ip_address_type if the selected subnets are IPv6 enabled.

Access Logs (`access_logs`) support the following:

* `bucket` - (Required) The S3 bucket name to store the logs in.
Expand Down