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

Add Outpost and COIP support to aws_lb datasource and resource #15170

Merged
merged 3 commits into from
Sep 18, 2020
Merged
Show file tree
Hide file tree
Changes from 2 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
9 changes: 9 additions & 0 deletions aws/data_source_aws_lb.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,10 @@ func dataSourceAwsLb() *schema.Resource {
Type: schema.TypeString,
Computed: true,
},
"outpost_id": {
Type: schema.TypeString,
Computed: true,
},
"allocation_id": {
Type: schema.TypeString,
Computed: true,
Expand Down Expand Up @@ -135,6 +139,11 @@ func dataSourceAwsLb() *schema.Resource {
Computed: true,
},

"customer_owned_ipv4_pool": {
Type: schema.TypeString,
Computed: true,
},

"tags": tagsSchemaComputed(),
},
}
Expand Down
104 changes: 104 additions & 0 deletions aws/data_source_aws_lb_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,39 @@ func TestAccDataSourceAWSLB_basic(t *testing.T) {
})
}

func TestAccDataSourceAWSLB_outpost(t *testing.T) {
lbName := fmt.Sprintf("testaccawslb-outpost-%s", acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum))
dataSourceName := "data.aws_lb.alb_test_with_arn"
resourceName := "aws_lb.alb_test"

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t); testAccPreCheckAWSOutpostsOutposts(t) },
Providers: testAccProviders,
Steps: []resource.TestStep{
{
Config: testAccDataSourceAWSLBConfigOutpost(lbName),
Check: resource.ComposeAggregateTestCheckFunc(
resource.TestCheckResourceAttrPair(dataSourceName, "name", resourceName, "name"),
resource.TestCheckResourceAttrPair(dataSourceName, "internal", resourceName, "internal"),
resource.TestCheckResourceAttrPair(dataSourceName, "subnets.#", resourceName, "subnets.#"),
resource.TestCheckResourceAttrPair(dataSourceName, "security_groups.#", resourceName, "security_groups.#"),
resource.TestCheckResourceAttrPair(dataSourceName, "tags.%", resourceName, "tags.%"),
resource.TestCheckResourceAttrPair(dataSourceName, "tags.TestName", resourceName, "tags.TestName"),
resource.TestCheckResourceAttrPair(dataSourceName, "enable_deletion_protection", resourceName, "enable_deletion_protection"),
resource.TestCheckResourceAttrPair(dataSourceName, "idle_timeout", resourceName, "idle_timeout"),
resource.TestCheckResourceAttrPair(dataSourceName, "vpc_id", resourceName, "vpc_id"),
resource.TestCheckResourceAttrPair(dataSourceName, "zone_id", resourceName, "zone_id"),
resource.TestCheckResourceAttrPair(dataSourceName, "dns_name", resourceName, "dns_name"),
resource.TestCheckResourceAttrPair(dataSourceName, "arn", resourceName, "arn"),
resource.TestCheckResourceAttrPair(dataSourceName, "ip_address_type", resourceName, "ip_address_type"),
resource.TestCheckResourceAttrPair(dataSourceName, "subnet_mapping.#", resourceName, "subnet_mapping.#"),
resource.TestCheckResourceAttrPair(dataSourceName, "subnet_mapping.0.outpost_id", resourceName, "subnet_mapping.0.outpost_id"),
),
},
},
})
}

func TestAccDataSourceAWSLB_BackwardsCompatibility(t *testing.T) {
lbName := fmt.Sprintf("testaccawsalb-basic-%s", acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum))
dataSourceName1 := "data.aws_alb.alb_test_with_arn"
Expand Down Expand Up @@ -192,6 +225,77 @@ data "aws_lb" "alb_test_with_name" {
`, lbName)
}

func testAccDataSourceAWSLBConfigOutpost(lbName string) string {
return fmt.Sprintf(`
data "aws_outposts_outposts" "test" {}

data "aws_outposts_outpost" "test" {
id = tolist(data.aws_outposts_outposts.test.ids)[0]
}

resource "aws_lb" "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_outpost"
}
}

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

tags = {
Name = "terraform-testacc-lb-data-source-outpost"
}
}

resource "aws_subnet" "alb_test" {
vpc_id = aws_vpc.alb_test.id
cidr_block = "10.0.0.0/24"
availability_zone = data.aws_outposts_outpost.test.availability_zone
outpost_arn = data.aws_outposts_outpost.test.arn
johnbarney marked this conversation as resolved.
Show resolved Hide resolved

tags = {
Name = "tf-acc-lb-data-source-outpost"
}
}

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

data "aws_lb" "alb_test_with_arn" {
arn = aws_lb.alb_test.arn
}
`, lbName)
}

func testAccDataSourceAWSLBConfigBackardsCompatibility(albName string) string {
return fmt.Sprintf(`
resource "aws_alb" "alb_test" {
Expand Down
20 changes: 19 additions & 1 deletion aws/resource_aws_lb.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,11 @@ func resourceAwsLb() *schema.Resource {
Required: true,
ForceNew: true,
},
"outpost_id": {
Type: schema.TypeString,
Computed: true,
Optional: true,
johnbarney marked this conversation as resolved.
Show resolved Hide resolved
},
"allocation_id": {
Type: schema.TypeString,
Optional: true,
Expand All @@ -128,6 +133,7 @@ func resourceAwsLb() *schema.Resource {
var buf bytes.Buffer
m := v.(map[string]interface{})
buf.WriteString(fmt.Sprintf("%s-", m["subnet_id"].(string)))
buf.WriteString(fmt.Sprintf("%s-", m["outpost_id"].(string)))
johnbarney marked this conversation as resolved.
Show resolved Hide resolved
if m["allocation_id"] != "" {
buf.WriteString(fmt.Sprintf("%s-", m["allocation_id"].(string)))
}
Expand Down Expand Up @@ -212,6 +218,12 @@ func resourceAwsLb() *schema.Resource {
}, false),
},

"customer_owned_ipv4_pool": {
Type: schema.TypeString,
Optional: true,
ForceNew: true,
},

"vpc_id": {
Type: schema.TypeString,
Computed: true,
Expand Down Expand Up @@ -297,6 +309,10 @@ func resourceAwsLbCreate(d *schema.ResourceData, meta interface{}) error {
elbOpts.IpAddressType = aws.String(v.(string))
}

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

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

resp, err := elbconn.CreateLoadBalancer(elbOpts)
Expand Down Expand Up @@ -700,6 +716,7 @@ func flattenSubnetMappingsFromAvailabilityZones(availabilityZones []*elbv2.Avail
for _, availabilityZone := range availabilityZones {
m := make(map[string]interface{})
m["subnet_id"] = aws.StringValue(availabilityZone.SubnetId)
m["outpost_id"] = aws.StringValue(availabilityZone.OutpostId)

for _, loadBalancerAddress := range availabilityZone.LoadBalancerAddresses {
m["allocation_id"] = aws.StringValue(loadBalancerAddress.AllocationId)
Expand Down Expand Up @@ -733,13 +750,14 @@ func flattenAwsLbResource(d *schema.ResourceData, meta interface{}, lb *elbv2.Lo
d.Set("arn", lb.LoadBalancerArn)
d.Set("arn_suffix", lbSuffixFromARN(lb.LoadBalancerArn))
d.Set("name", lb.LoadBalancerName)
d.Set("internal", (lb.Scheme != nil && aws.StringValue(lb.Scheme) == "internal"))
d.Set("internal", lb.Scheme != nil && aws.StringValue(lb.Scheme) == "internal")
d.Set("security_groups", flattenStringList(lb.SecurityGroups))
d.Set("vpc_id", lb.VpcId)
d.Set("zone_id", lb.CanonicalHostedZoneId)
d.Set("dns_name", lb.DNSName)
d.Set("ip_address_type", lb.IpAddressType)
d.Set("load_balancer_type", lb.Type)
d.Set("customer_owned_ipv4_pool", lb.CustomerOwnedIpv4Pool)

if err := d.Set("subnets", flattenSubnetsFromAvailabilityZones(lb.AvailabilityZones)); err != nil {
return fmt.Errorf("error setting subnets: %s", err)
Expand Down
126 changes: 126 additions & 0 deletions aws/resource_aws_lb_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,45 @@ func TestAccAWSLB_NLB_basic(t *testing.T) {
})
}

func TestAccAWSLB_ALB_outpost(t *testing.T) {
var conf elbv2.LoadBalancer
lbName := fmt.Sprintf("testaccawslb-outpost-%s", acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum))
resourceName := "aws_lb.lb_test"

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t); testAccPreCheckAWSOutpostsOutposts(t) },
IDRefreshName: resourceName,
Providers: testAccProviders,
CheckDestroy: testAccCheckAWSLBDestroy,
Steps: []resource.TestStep{
{
Config: testAccAWSLBConfig_outpost(lbName),
Check: resource.ComposeAggregateTestCheckFunc(
testAccCheckAWSLBExists(resourceName, &conf),
resource.TestCheckResourceAttr(resourceName, "access_logs.#", "1"),
resource.TestCheckResourceAttr(resourceName, "access_logs.0.enabled", "false"),
testAccMatchResourceAttrRegionalARN(resourceName, "arn", "elasticloadbalancing", regexp.MustCompile(fmt.Sprintf("loadbalancer/app/%s/.+", lbName))),
resource.TestCheckResourceAttrSet(resourceName, "dns_name"),
resource.TestCheckResourceAttr(resourceName, "enable_deletion_protection", "false"),
resource.TestCheckResourceAttr(resourceName, "idle_timeout", "30"),
resource.TestCheckResourceAttr(resourceName, "ip_address_type", "ipv4"),
resource.TestCheckResourceAttr(resourceName, "load_balancer_type", "application"),
resource.TestCheckResourceAttr(resourceName, "name", lbName),
resource.TestCheckResourceAttr(resourceName, "security_groups.#", "1"),
resource.TestCheckResourceAttr(resourceName, "subnets.#", "1"),
resource.TestCheckResourceAttr(resourceName, "tags.%", "1"),
resource.TestCheckResourceAttr(resourceName, "tags.Name", "TestAccAWSALB_outpost"),
resource.TestCheckResourceAttr(resourceName, "subnet_mapping.#", "1"),
resource.TestCheckResourceAttrSet(resourceName, "subnet_mapping.0.outpost_id"),
resource.TestCheckResourceAttrSet(resourceName, "customer_owned_ipv4_pool"),
resource.TestCheckResourceAttrSet(resourceName, "vpc_id"),
resource.TestCheckResourceAttrSet(resourceName, "zone_id"),
),
},
},
})
}

func TestAccAWSLB_networkLoadbalancerEIP(t *testing.T) {
var conf elbv2.LoadBalancer
resourceName := "aws_lb.lb_test"
Expand Down Expand Up @@ -1384,6 +1423,93 @@ resource "aws_security_group" "alb_test" {
`, lbName))
}

func testAccAWSLBConfig_outpost(lbName string) string {
return composeConfig(testAccAvailableAZsNoOptInConfig(), fmt.Sprintf(`
data "aws_outposts_outposts" "test" {}

data "aws_outposts_outpost" "test" {
id = tolist(data.aws_outposts_outposts.test.ids)[0]
}

data "aws_ec2_coip_pools" "test" {}

data "aws_ec2_local_gateway_route_table" "test" {
outpost_arn = tolist(data.aws_outposts_outposts.test.arns)[0]
}

resource "aws_ec2_local_gateway_route_table_vpc_association" "test" {
local_gateway_route_table_id = data.aws_ec2_local_gateway_route_table.test.id
vpc_id = aws_vpc.alb_test.id
}

resource "aws_route_table" "test" {
vpc_id = aws_vpc.alb_test.id
depends_on = [aws_ec2_local_gateway_route_table_vpc_association.test]
}

resource "aws_route_table_association" "a" {
subnet_id = aws_subnet.alb_test.id
route_table_id = aws_route_table.test.id
}

resource "aws_lb" "lb_test" {
name = "%s"
security_groups = [aws_security_group.alb_test.id]
customer_owned_ipv4_pool = tolist(data.aws_ec2_coip_pools.test.pool_ids)[0]
idle_timeout = 30
enable_deletion_protection = false
subnets = [aws_subnet.alb_test.id]

tags = {
Name = "TestAccAWSALB_outpost"
}
}

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

tags = {
Name = "terraform-testacc-lb-outpost"
}
}

resource "aws_subnet" "alb_test" {
vpc_id = aws_vpc.alb_test.id
cidr_block = "10.0.0.0/24"
availability_zone = data.aws_outposts_outpost.test.availability_zone
outpost_arn = data.aws_outposts_outpost.test.arn
johnbarney marked this conversation as resolved.
Show resolved Hide resolved

tags = {
Name = "tf-acc-lb-outpost"
}
}

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 = {
Name = "TestAccAWSALB_outpost"
}
}
`, lbName))
}

func testAccAWSLBConfig_enableHttp2(lbName string, http2 bool) string {
return composeConfig(testAccAvailableAZsNoOptInConfig(), fmt.Sprintf(`
resource "aws_lb" "lb_test" {
Expand Down
2 changes: 2 additions & 0 deletions website/docs/r/lb.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ for load balancers of type `network` will force a recreation of the resource.
* `enable_cross_zone_load_balancing` - (Optional) If true, cross-zone load balancing of the load balancer will be enabled.
This is a `network` load balancer feature. Defaults to `false`.
* `enable_http2` - (Optional) Indicates whether HTTP/2 is enabled in `application` load balancers. Defaults to `true`.
* `customer_owned_ipv4_pool` - (Optional) The ID of the customer owned ipv4 pool to use for this load balancer.
* `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 map of tags to assign to the resource.

Expand All @@ -144,6 +145,7 @@ The following attributes are exported in addition to the arguments listed above:
* `arn_suffix` - The ARN suffix for use with CloudWatch Metrics.
* `dns_name` - The DNS name of the load balancer.
* `zone_id` - The canonical hosted zone ID of the load balancer (to be used in a Route 53 Alias record).
* `subnet_mapping.*.outpost_id` - ID of the Outpost containing the load balancer.

## Timeouts

Expand Down