provider/aws: Add `aws_alb` resource
This commit adds a resource, acceptance tests and documentation for the new Application Load Balancer (aws_alb). We choose to use the name alb over the package name, elbv2, in order to avoid confusion. This is the first in a series of commits to fully support the new resources necessary for Application Load Balancers.
This commit is contained in:
parent
ebdfe76530
commit
0b421b6998
|
@ -152,6 +152,7 @@ func Provider() terraform.ResourceProvider {
|
|||
},
|
||||
|
||||
ResourcesMap: map[string]*schema.Resource{
|
||||
"aws_alb": resourceAwsAlb(),
|
||||
"aws_ami": resourceAwsAmi(),
|
||||
"aws_ami_copy": resourceAwsAmiCopy(),
|
||||
"aws_ami_from_instance": resourceAwsAmiFromInstance(),
|
||||
|
|
|
@ -0,0 +1,337 @@
|
|||
package aws
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"strconv"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/service/elbv2"
|
||||
"github.com/hashicorp/errwrap"
|
||||
"github.com/hashicorp/terraform/helper/schema"
|
||||
)
|
||||
|
||||
func resourceAwsAlb() *schema.Resource {
|
||||
return &schema.Resource{
|
||||
Create: resourceAwsAlbCreate,
|
||||
Read: resourceAwsAlbRead,
|
||||
Update: resourceAwsAlbUpdate,
|
||||
Delete: resourceAwsAlbDelete,
|
||||
Importer: &schema.ResourceImporter{
|
||||
State: schema.ImportStatePassthrough,
|
||||
},
|
||||
|
||||
Schema: map[string]*schema.Schema{
|
||||
"name": {
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
ForceNew: true,
|
||||
ValidateFunc: validateElbName,
|
||||
},
|
||||
|
||||
"internal": {
|
||||
Type: schema.TypeBool,
|
||||
Optional: true,
|
||||
ForceNew: true,
|
||||
Computed: true,
|
||||
},
|
||||
|
||||
"security_groups": {
|
||||
Type: schema.TypeSet,
|
||||
Elem: &schema.Schema{Type: schema.TypeString},
|
||||
ForceNew: true,
|
||||
Optional: true,
|
||||
Set: schema.HashString,
|
||||
},
|
||||
|
||||
"subnets": {
|
||||
Type: schema.TypeSet,
|
||||
Elem: &schema.Schema{Type: schema.TypeString},
|
||||
ForceNew: true,
|
||||
Required: true,
|
||||
Set: schema.HashString,
|
||||
},
|
||||
|
||||
"access_logs": {
|
||||
Type: schema.TypeList,
|
||||
Optional: true,
|
||||
MaxItems: 1,
|
||||
Elem: &schema.Resource{
|
||||
Schema: map[string]*schema.Schema{
|
||||
"bucket": {
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
},
|
||||
"prefix": {
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
"enable_deletion_protection": {
|
||||
Type: schema.TypeBool,
|
||||
Optional: true,
|
||||
Default: false,
|
||||
},
|
||||
|
||||
"idle_timeout": {
|
||||
Type: schema.TypeInt,
|
||||
Optional: true,
|
||||
Default: 60,
|
||||
},
|
||||
|
||||
"vpc_id": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
|
||||
"zone_id": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
|
||||
"dns_name": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
|
||||
"tags": tagsSchema(),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func resourceAwsAlbCreate(d *schema.ResourceData, meta interface{}) error {
|
||||
elbconn := meta.(*AWSClient).elbv2conn
|
||||
|
||||
elbOpts := &elbv2.CreateLoadBalancerInput{
|
||||
Name: aws.String(d.Get("name").(string)),
|
||||
Tags: tagsFromMapELBv2(d.Get("tags").(map[string]interface{})),
|
||||
}
|
||||
|
||||
if scheme, ok := d.GetOk("internal"); ok && scheme.(bool) {
|
||||
elbOpts.Scheme = aws.String("internal")
|
||||
}
|
||||
|
||||
if v, ok := d.GetOk("security_groups"); ok {
|
||||
elbOpts.SecurityGroups = expandStringList(v.(*schema.Set).List())
|
||||
}
|
||||
|
||||
if v, ok := d.GetOk("subnets"); ok {
|
||||
elbOpts.Subnets = expandStringList(v.(*schema.Set).List())
|
||||
}
|
||||
|
||||
log.Printf("[DEBUG] ALB create configuration: %#v", elbOpts)
|
||||
|
||||
resp, err := elbconn.CreateLoadBalancer(elbOpts)
|
||||
if err != nil {
|
||||
return errwrap.Wrapf("Error creating Application Load Balancer: {{err}}", err)
|
||||
}
|
||||
|
||||
if len(resp.LoadBalancers) != 1 {
|
||||
return fmt.Errorf("No load balancers returned following creation of %s", d.Get("name").(string))
|
||||
}
|
||||
|
||||
d.SetId(*resp.LoadBalancers[0].LoadBalancerArn)
|
||||
log.Printf("[INFO] ALB ID: %s", d.Id())
|
||||
|
||||
return resourceAwsAlbUpdate(d, meta)
|
||||
}
|
||||
|
||||
func resourceAwsAlbRead(d *schema.ResourceData, meta interface{}) error {
|
||||
elbconn := meta.(*AWSClient).elbv2conn
|
||||
albArn := d.Id()
|
||||
|
||||
describeAlbOpts := &elbv2.DescribeLoadBalancersInput{
|
||||
LoadBalancerArns: []*string{aws.String(albArn)},
|
||||
}
|
||||
|
||||
describeResp, err := elbconn.DescribeLoadBalancers(describeAlbOpts)
|
||||
if err != nil {
|
||||
if isLoadBalancerNotFound(err) {
|
||||
// The ALB is gone now, so just remove it from the state
|
||||
log.Printf("[WARN] ALB %s not found in AWS, removing from state", d.Id())
|
||||
d.SetId("")
|
||||
return nil
|
||||
}
|
||||
|
||||
return errwrap.Wrapf("Error retrieving ALB: {{err}}", err)
|
||||
}
|
||||
if len(describeResp.LoadBalancers) != 1 {
|
||||
return fmt.Errorf("Unable to find ALB: %#v", describeResp.LoadBalancers)
|
||||
}
|
||||
|
||||
alb := describeResp.LoadBalancers[0]
|
||||
|
||||
d.Set("name", alb.LoadBalancerName)
|
||||
d.Set("internal", (alb.Scheme != nil && *alb.Scheme == "internal"))
|
||||
d.Set("security_groups", flattenStringList(alb.SecurityGroups))
|
||||
d.Set("subnets", flattenSubnetsFromAvailabilityZones(alb.AvailabilityZones))
|
||||
d.Set("vpc_id", alb.VpcId)
|
||||
d.Set("zone_id", alb.CanonicalHostedZoneId)
|
||||
d.Set("dns_name", alb.DNSName)
|
||||
|
||||
respTags, err := elbconn.DescribeTags(&elbv2.DescribeTagsInput{
|
||||
ResourceArns: []*string{alb.LoadBalancerArn},
|
||||
})
|
||||
if err != nil {
|
||||
return errwrap.Wrapf("Error retrieving ALB Tags: {{err}}", err)
|
||||
}
|
||||
|
||||
var et []*elbv2.Tag
|
||||
if len(respTags.TagDescriptions) > 0 {
|
||||
et = respTags.TagDescriptions[0].Tags
|
||||
}
|
||||
d.Set("tags", tagsToMapELBv2(et))
|
||||
|
||||
attributesResp, err := elbconn.DescribeLoadBalancerAttributes(&elbv2.DescribeLoadBalancerAttributesInput{
|
||||
LoadBalancerArn: aws.String(d.Id()),
|
||||
})
|
||||
if err != nil {
|
||||
return errwrap.Wrapf("Error retrieving ALB Attributes: {{err}}", err)
|
||||
}
|
||||
|
||||
accessLogMap := map[string]interface{}{}
|
||||
for _, attr := range attributesResp.Attributes {
|
||||
switch *attr.Key {
|
||||
case "access_logs.s3.bucket":
|
||||
accessLogMap["bucket"] = *attr.Value
|
||||
case "access_logs.s3.prefix":
|
||||
accessLogMap["prefix"] = *attr.Value
|
||||
case "idle_timeout.timeout_seconds":
|
||||
timeout, err := strconv.Atoi(*attr.Value)
|
||||
if err != nil {
|
||||
return errwrap.Wrapf("Error parsing ALB timeout: {{err}}", err)
|
||||
}
|
||||
log.Printf("[DEBUG] Setting ALB Timeout Seconds: %d", timeout)
|
||||
d.Set("idle_timeout", timeout)
|
||||
case "deletion_protection.enabled":
|
||||
protectionEnabled := (*attr.Value) == "true"
|
||||
log.Printf("[DEBUG] Setting ALB Deletion Protection Enabled: %t", protectionEnabled)
|
||||
d.Set("enable_deletion_protection", protectionEnabled)
|
||||
}
|
||||
}
|
||||
|
||||
log.Printf("[DEBUG] Setting ALB Access Logs: %#v", accessLogMap)
|
||||
if accessLogMap["bucket"] != "" || accessLogMap["prefix"] != "" {
|
||||
d.Set("access_logs", []interface{}{accessLogMap})
|
||||
} else {
|
||||
d.Set("access_logs", []interface{}{})
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func resourceAwsAlbUpdate(d *schema.ResourceData, meta interface{}) error {
|
||||
elbconn := meta.(*AWSClient).elbv2conn
|
||||
|
||||
attributes := make([]*elbv2.LoadBalancerAttribute, 0)
|
||||
|
||||
if d.HasChange("access_logs") {
|
||||
logs := d.Get("access_logs").([]interface{})
|
||||
if len(logs) == 1 {
|
||||
log := logs[0].(map[string]interface{})
|
||||
|
||||
attributes = append(attributes,
|
||||
&elbv2.LoadBalancerAttribute{
|
||||
Key: aws.String("access_logs.s3.enabled"),
|
||||
Value: aws.String("true"),
|
||||
},
|
||||
&elbv2.LoadBalancerAttribute{
|
||||
Key: aws.String("access_logs.s3.bucket"),
|
||||
Value: aws.String(log["bucket"].(string)),
|
||||
})
|
||||
|
||||
if prefix, ok := log["prefix"]; ok {
|
||||
attributes = append(attributes, &elbv2.LoadBalancerAttribute{
|
||||
Key: aws.String("access_logs.s3.prefix"),
|
||||
Value: aws.String(prefix.(string)),
|
||||
})
|
||||
}
|
||||
} else if len(logs) == 0 {
|
||||
attributes = append(attributes, &elbv2.LoadBalancerAttribute{
|
||||
Key: aws.String("access_logs.s3.enabled"),
|
||||
Value: aws.String("false"),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
if d.HasChange("enable_deletion_protection") {
|
||||
attributes = append(attributes, &elbv2.LoadBalancerAttribute{
|
||||
Key: aws.String("deletion_protection.enabled"),
|
||||
Value: aws.String(fmt.Sprintf("%t", d.Get("enable_deletion_protection").(bool))),
|
||||
})
|
||||
}
|
||||
|
||||
if d.HasChange("idle_timeout") {
|
||||
attributes = append(attributes, &elbv2.LoadBalancerAttribute{
|
||||
Key: aws.String("idle_timeout.timeout_seconds"),
|
||||
Value: aws.String(fmt.Sprintf("%d", d.Get("idle_timeout").(int))),
|
||||
})
|
||||
}
|
||||
|
||||
if len(attributes) != 0 {
|
||||
input := &elbv2.ModifyLoadBalancerAttributesInput{
|
||||
LoadBalancerArn: aws.String(d.Id()),
|
||||
Attributes: attributes,
|
||||
}
|
||||
|
||||
log.Printf("[DEBUG] ALB Modify Load Balancer Attributes Request: %#v", input)
|
||||
_, err := elbconn.ModifyLoadBalancerAttributes(input)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Failure configuring ALB attributes: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
return resourceAwsAlbRead(d, meta)
|
||||
}
|
||||
|
||||
func resourceAwsAlbDelete(d *schema.ResourceData, meta interface{}) error {
|
||||
albconn := meta.(*AWSClient).elbv2conn
|
||||
|
||||
log.Printf("[INFO] Deleting ALB: %s", d.Id())
|
||||
|
||||
// Destroy the load balancer
|
||||
deleteElbOpts := elbv2.DeleteLoadBalancerInput{
|
||||
LoadBalancerArn: aws.String(d.Id()),
|
||||
}
|
||||
if _, err := albconn.DeleteLoadBalancer(&deleteElbOpts); err != nil {
|
||||
return fmt.Errorf("Error deleting ALB: %s", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// tagsToMapELBv2 turns the list of tags into a map.
|
||||
func tagsToMapELBv2(ts []*elbv2.Tag) map[string]string {
|
||||
result := make(map[string]string)
|
||||
for _, t := range ts {
|
||||
result[*t.Key] = *t.Value
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
// tagsFromMapELBv2 returns the tags for the given map of data.
|
||||
func tagsFromMapELBv2(m map[string]interface{}) []*elbv2.Tag {
|
||||
var result []*elbv2.Tag
|
||||
for k, v := range m {
|
||||
result = append(result, &elbv2.Tag{
|
||||
Key: aws.String(k),
|
||||
Value: aws.String(v.(string)),
|
||||
})
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
// flattenSubnetsFromAvailabilityZones creates a slice of strings containing the subnet IDs
|
||||
// for the ALB based on the AvailabilityZones structure returned by the API.
|
||||
func flattenSubnetsFromAvailabilityZones(availabilityZones []*elbv2.AvailabilityZone) []string {
|
||||
var result []string
|
||||
for _, az := range availabilityZones {
|
||||
result = append(result, *az.SubnetId)
|
||||
}
|
||||
return result
|
||||
}
|
|
@ -0,0 +1,336 @@
|
|||
package aws
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/service/elbv2"
|
||||
"github.com/hashicorp/errwrap"
|
||||
"github.com/hashicorp/terraform/helper/acctest"
|
||||
"github.com/hashicorp/terraform/helper/resource"
|
||||
"github.com/hashicorp/terraform/terraform"
|
||||
)
|
||||
|
||||
func TestAccAWSALB_basic(t *testing.T) {
|
||||
var conf 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: testAccAWSALBConfig_basic(albName),
|
||||
Check: resource.ComposeAggregateTestCheckFunc(
|
||||
testAccCheckAWSALBExists("aws_alb.alb_test", &conf),
|
||||
resource.TestCheckResourceAttr("aws_alb.alb_test", "name", albName),
|
||||
resource.TestCheckResourceAttr("aws_alb.alb_test", "internal", "false"),
|
||||
resource.TestCheckResourceAttr("aws_alb.alb_test", "subnets.#", "2"),
|
||||
resource.TestCheckResourceAttr("aws_alb.alb_test", "security_groups.#", "1"),
|
||||
resource.TestCheckResourceAttr("aws_alb.alb_test", "tags.%", "1"),
|
||||
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.TestCheckResourceAttrSet("aws_alb.alb_test", "vpc_id"),
|
||||
resource.TestCheckResourceAttrSet("aws_alb.alb_test", "zone_id"),
|
||||
resource.TestCheckResourceAttrSet("aws_alb.alb_test", "dns_name"),
|
||||
),
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func TestAccAWSALB_accesslogs(t *testing.T) {
|
||||
var conf elbv2.LoadBalancer
|
||||
bucketName := fmt.Sprintf("testaccawsalbaccesslogs-%s", acctest.RandStringFromCharSet(6, acctest.CharSetAlphaNum))
|
||||
albName := fmt.Sprintf("testaccawsalbaccesslog-%s", acctest.RandStringFromCharSet(4, acctest.CharSetAlpha))
|
||||
|
||||
resource.Test(t, resource.TestCase{
|
||||
PreCheck: func() { testAccPreCheck(t) },
|
||||
IDRefreshName: "aws_alb.alb_test",
|
||||
Providers: testAccProviders,
|
||||
CheckDestroy: testAccCheckAWSALBDestroy,
|
||||
Steps: []resource.TestStep{
|
||||
{
|
||||
Config: testAccAWSALBConfig_basic(albName),
|
||||
Check: resource.ComposeAggregateTestCheckFunc(
|
||||
testAccCheckAWSALBExists("aws_alb.alb_test", &conf),
|
||||
resource.TestCheckResourceAttr("aws_alb.alb_test", "name", albName),
|
||||
resource.TestCheckResourceAttr("aws_alb.alb_test", "internal", "false"),
|
||||
resource.TestCheckResourceAttr("aws_alb.alb_test", "subnets.#", "2"),
|
||||
resource.TestCheckResourceAttr("aws_alb.alb_test", "security_groups.#", "1"),
|
||||
resource.TestCheckResourceAttr("aws_alb.alb_test", "tags.%", "1"),
|
||||
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.TestCheckResourceAttrSet("aws_alb.alb_test", "vpc_id"),
|
||||
resource.TestCheckResourceAttrSet("aws_alb.alb_test", "zone_id"),
|
||||
resource.TestCheckResourceAttrSet("aws_alb.alb_test", "dns_name"),
|
||||
),
|
||||
},
|
||||
|
||||
{
|
||||
Config: testAccAWSALBConfig_accessLogs(albName, bucketName),
|
||||
Check: resource.ComposeAggregateTestCheckFunc(
|
||||
testAccCheckAWSALBExists("aws_alb.alb_test", &conf),
|
||||
resource.TestCheckResourceAttr("aws_alb.alb_test", "name", albName),
|
||||
resource.TestCheckResourceAttr("aws_alb.alb_test", "internal", "false"),
|
||||
resource.TestCheckResourceAttr("aws_alb.alb_test", "subnets.#", "2"),
|
||||
resource.TestCheckResourceAttr("aws_alb.alb_test", "security_groups.#", "1"),
|
||||
resource.TestCheckResourceAttr("aws_alb.alb_test", "tags.%", "1"),
|
||||
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", "50"),
|
||||
resource.TestCheckResourceAttrSet("aws_alb.alb_test", "vpc_id"),
|
||||
resource.TestCheckResourceAttrSet("aws_alb.alb_test", "zone_id"),
|
||||
resource.TestCheckResourceAttrSet("aws_alb.alb_test", "dns_name"),
|
||||
resource.TestCheckResourceAttr("aws_alb.alb_test", "access_logs.#", "1"),
|
||||
resource.TestCheckResourceAttr("aws_alb.alb_test", "access_logs.0.bucket", bucketName),
|
||||
resource.TestCheckResourceAttr("aws_alb.alb_test", "access_logs.0.prefix", "testAccAWSALBConfig_accessLogs"),
|
||||
),
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func testAccCheckAWSALBExists(n string, res *elbv2.LoadBalancer) resource.TestCheckFunc {
|
||||
return func(s *terraform.State) error {
|
||||
rs, ok := s.RootModule().Resources[n]
|
||||
if !ok {
|
||||
return fmt.Errorf("Not found: %s", n)
|
||||
}
|
||||
|
||||
if rs.Primary.ID == "" {
|
||||
return errors.New("No ALB ID is set")
|
||||
}
|
||||
|
||||
conn := testAccProvider.Meta().(*AWSClient).elbv2conn
|
||||
|
||||
describe, err := conn.DescribeLoadBalancers(&elbv2.DescribeLoadBalancersInput{
|
||||
LoadBalancerArns: []*string{aws.String(rs.Primary.ID)},
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(describe.LoadBalancers) != 1 ||
|
||||
*describe.LoadBalancers[0].LoadBalancerArn != rs.Primary.ID {
|
||||
return errors.New("ALB not found")
|
||||
}
|
||||
|
||||
*res = *describe.LoadBalancers[0]
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func testAccCheckAWSALBDestroy(s *terraform.State) error {
|
||||
conn := testAccProvider.Meta().(*AWSClient).elbv2conn
|
||||
|
||||
for _, rs := range s.RootModule().Resources {
|
||||
if rs.Type != "aws_alb" {
|
||||
continue
|
||||
}
|
||||
|
||||
describe, err := conn.DescribeLoadBalancers(&elbv2.DescribeLoadBalancersInput{
|
||||
LoadBalancerArns: []*string{aws.String(rs.Primary.ID)},
|
||||
})
|
||||
|
||||
if err == nil {
|
||||
if len(describe.LoadBalancers) != 0 &&
|
||||
*describe.LoadBalancers[0].LoadBalancerArn == rs.Primary.ID {
|
||||
return fmt.Errorf("ALB %q still exists", rs.Primary.ID)
|
||||
}
|
||||
}
|
||||
|
||||
// Verify the error
|
||||
if isLoadBalancerNotFound(err) {
|
||||
return nil
|
||||
} else {
|
||||
return errwrap.Wrapf("Unexpected error checking ALB destroyed: {{err}}", err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func testAccAWSALBConfig_basic(albName string) string {
|
||||
return fmt.Sprintf(`resource "aws_alb" "alb_test" {
|
||||
name = "%s"
|
||||
internal = false
|
||||
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"
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
func testAccAWSALBConfig_accessLogs(albName, bucketName string) string {
|
||||
return fmt.Sprintf(`resource "aws_alb" "alb_test" {
|
||||
name = "%s"
|
||||
internal = false
|
||||
security_groups = ["${aws_security_group.alb_test.id}"]
|
||||
subnets = ["${aws_subnet.alb_test.*.id}"]
|
||||
|
||||
idle_timeout = 50
|
||||
enable_deletion_protection = false
|
||||
|
||||
access_logs {
|
||||
bucket = "${aws_s3_bucket.logs.bucket}"
|
||||
prefix = "${var.bucket_prefix}"
|
||||
}
|
||||
|
||||
tags {
|
||||
TestName = "TestAccAWSALB_basic"
|
||||
}
|
||||
}
|
||||
|
||||
variable "bucket_name" {
|
||||
type = "string"
|
||||
default = "%s"
|
||||
}
|
||||
|
||||
variable "bucket_prefix" {
|
||||
type = "string"
|
||||
default = "testAccAWSALBConfig_accessLogs"
|
||||
}
|
||||
|
||||
resource "aws_s3_bucket" "logs" {
|
||||
bucket = "${var.bucket_name}"
|
||||
policy = "${data.aws_iam_policy_document.logs_bucket.json}"
|
||||
# dangerous, only here for the test...
|
||||
force_destroy = true
|
||||
|
||||
tags {
|
||||
Name = "ALB Logs Bucket Test"
|
||||
}
|
||||
}
|
||||
|
||||
data "aws_caller_identity" "current" {}
|
||||
|
||||
data "aws_elb_service_account" "current" {}
|
||||
|
||||
data "aws_iam_policy_document" "logs_bucket" {
|
||||
statement {
|
||||
actions = ["s3:PutObject"]
|
||||
effect = "Allow"
|
||||
resources = ["arn:aws:s3:::${var.bucket_name}/${var.bucket_prefix}/AWSLogs/${data.aws_caller_identity.current.account_id}/*"]
|
||||
|
||||
principals = {
|
||||
type = "AWS"
|
||||
identifiers = ["arn:aws:iam::${data.aws_elb_service_account.current.id}:root"]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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, bucketName)
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
---
|
||||
layout: "aws"
|
||||
page_title: "AWS: aws_alb"
|
||||
sidebar_current: "docs-aws-resource-alb"
|
||||
description: |-
|
||||
Provides an Application Load Balancer resource.
|
||||
---
|
||||
|
||||
# aws\_alb
|
||||
|
||||
Provides an Application Load Balancer resource.
|
||||
|
||||
## Example Usage
|
||||
|
||||
```
|
||||
# Create a new load balancer
|
||||
resource "aws_alb" "test" {
|
||||
name = "test-alb-tf"
|
||||
internal = false
|
||||
security_groups = ["${aws_security_group.alb_sg.id}"]
|
||||
subnets = ["${aws_subnet.public.*.id}"]
|
||||
|
||||
enable_deletion_protection = true
|
||||
|
||||
access_logs {
|
||||
bucket = "${aws_s3_bucket.alb_logs.bucket}"
|
||||
prefix = "test-alb"
|
||||
}
|
||||
|
||||
tags {
|
||||
Environment = "production"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Argument Reference
|
||||
|
||||
The following arguments are supported:
|
||||
|
||||
* `name` - (Optional) The name of the ALB. By default generated by Terraform.
|
||||
* `internal` - (Optional) If true, the ALB will be internal.
|
||||
* `security_groups` - (Optional) A list of security group IDs to assign to the ELB.
|
||||
* `access_logs` - (Optional) An Access Logs block. Access Logs documented below.
|
||||
* `subnets` - (Required) A list of subnet IDs to attach to the ELB.
|
||||
* `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.
|
||||
* `tags` - (Optional) A mapping of tags to assign to the resource.
|
||||
|
||||
Access Logs (`access_logs`) support the following:
|
||||
|
||||
* `bucket` - (Required) The S3 bucket name to store the logs in.
|
||||
* `prefix` - (Optional) The S3 bucket prefix. Logs are stored in the root if not configured.
|
||||
|
||||
## Attributes Reference
|
||||
|
||||
The following attributes are exported in addition to the arguments listed above:
|
||||
|
||||
* `id` - The ARN of the load balancer
|
||||
* `dns_name` - The DNS name of the load balancer
|
||||
* `canonical_hosted_zone_id` - The canonical hosted zone ID of the load balancer.
|
||||
* `zone_id` - The canonical hosted zone ID of the load balancer (to be used in a Route 53 Alias record)
|
||||
|
||||
## Import
|
||||
|
||||
ALBs can be imported using their ARN, e.g.
|
||||
|
||||
```
|
||||
$ terraform import aws_alb.bar arn:aws:elasticloadbalancing:us-west-2:123456789012:loadbalancer/app/my-load-balancer/50dc6c495c0c9188
|
||||
```
|
|
@ -206,10 +206,14 @@
|
|||
</li>
|
||||
|
||||
|
||||
<li<%= sidebar_current(/^docs-aws-resource-(ami|app|autoscaling|ebs|elb|eip|instance|launch|lb|proxy|spot|volume|placement|key-pair|elb_attachment|load-balancer)/) %>>
|
||||
<li<%= sidebar_current(/^docs-aws-resource-(alb|ami|app|autoscaling|ebs|elb|eip|instance|launch|lb|proxy|spot|volume|placement|key-pair|elb_attachment|load-balancer)/) %>>
|
||||
<a href="#">EC2 Resources</a>
|
||||
<ul class="nav nav-visible">
|
||||
|
||||
<li<%= sidebar_current("docs-aws-resource-alb") %>>
|
||||
<a href="/docs/providers/aws/r/alb.html">aws_alb</a>
|
||||
</li>
|
||||
|
||||
<li<%= sidebar_current("docs-aws-resource-ami") %>>
|
||||
<a href="/docs/providers/aws/r/ami.html">aws_ami</a>
|
||||
</li>
|
||||
|
|
Loading…
Reference in New Issue