Skip to content

Commit e4ce708

Browse files
committed
provider/aws: Add aws_alb_target_group_attachment
1 parent 6a2e568 commit e4ce708

5 files changed

Lines changed: 340 additions & 0 deletions

File tree

builtin/providers/aws/provider.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,7 @@ func Provider() terraform.ResourceProvider {
156156
"aws_alb_listener": resourceAwsAlbListener(),
157157
"aws_alb_listener_rule": resourceAwsAlbListenerRule(),
158158
"aws_alb_target_group": resourceAwsAlbTargetGroup(),
159+
"aws_alb_target_group_attachment": resourceAwsAlbTargetGroupAttachment(),
159160
"aws_ami": resourceAwsAmi(),
160161
"aws_ami_copy": resourceAwsAmiCopy(),
161162
"aws_ami_from_instance": resourceAwsAmiFromInstance(),
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
package aws
2+
3+
import (
4+
"fmt"
5+
"log"
6+
7+
"github.com/aws/aws-sdk-go/aws"
8+
"github.com/aws/aws-sdk-go/aws/awserr"
9+
"github.com/aws/aws-sdk-go/service/elbv2"
10+
"github.com/hashicorp/errwrap"
11+
"github.com/hashicorp/terraform/helper/resource"
12+
"github.com/hashicorp/terraform/helper/schema"
13+
)
14+
15+
func resourceAwsAlbTargetGroupAttachment() *schema.Resource {
16+
return &schema.Resource{
17+
Create: resourceAwsAlbAttachmentCreate,
18+
Read: resourceAwsAlbAttachmentRead,
19+
Delete: resourceAwsAlbAttachmentDelete,
20+
21+
Schema: map[string]*schema.Schema{
22+
"target_group_arn": {
23+
Type: schema.TypeString,
24+
ForceNew: true,
25+
Required: true,
26+
},
27+
28+
"target_id": {
29+
Type: schema.TypeString,
30+
ForceNew: true,
31+
Required: true,
32+
},
33+
34+
"port": {
35+
Type: schema.TypeInt,
36+
ForceNew: true,
37+
Required: true,
38+
},
39+
},
40+
}
41+
}
42+
43+
func resourceAwsAlbAttachmentCreate(d *schema.ResourceData, meta interface{}) error {
44+
elbconn := meta.(*AWSClient).elbv2conn
45+
46+
params := &elbv2.RegisterTargetsInput{
47+
TargetGroupArn: aws.String(d.Get("target_group_arn").(string)),
48+
Targets: []*elbv2.TargetDescription{
49+
{
50+
Id: aws.String(d.Get("target_id").(string)),
51+
Port: aws.Int64(int64(d.Get("port").(int))),
52+
},
53+
},
54+
}
55+
56+
log.Printf("[INFO] Registering Target %s (%d) with Target Group %s", d.Get("target_id").(string),
57+
d.Get("port").(int), d.Get("target_group_arn").(string))
58+
59+
_, err := elbconn.RegisterTargets(params)
60+
if err != nil {
61+
return errwrap.Wrapf("Error registering targets with target group: {{err}}", err)
62+
}
63+
64+
d.SetId(resource.PrefixedUniqueId(fmt.Sprintf("%s-", d.Get("target_group_arn"))))
65+
66+
return nil
67+
}
68+
69+
func resourceAwsAlbAttachmentDelete(d *schema.ResourceData, meta interface{}) error {
70+
elbconn := meta.(*AWSClient).elbv2conn
71+
72+
params := &elbv2.DeregisterTargetsInput{
73+
TargetGroupArn: aws.String(d.Get("target_group_arn").(string)),
74+
Targets: []*elbv2.TargetDescription{
75+
{
76+
Id: aws.String(d.Get("target_id").(string)),
77+
Port: aws.Int64(int64(d.Get("port").(int))),
78+
},
79+
},
80+
}
81+
82+
_, err := elbconn.DeregisterTargets(params)
83+
if err != nil && !isTargetGroupNotFound(err) {
84+
return errwrap.Wrapf("Error deregistering Targets: {{err}}", err)
85+
}
86+
87+
d.SetId("")
88+
89+
return nil
90+
}
91+
92+
// resourceAwsAlbAttachmentRead requires all of the fields in order to describe the correct
93+
// target, so there is no work to do beyond ensuring that the target and group still exist.
94+
func resourceAwsAlbAttachmentRead(d *schema.ResourceData, meta interface{}) error {
95+
elbconn := meta.(*AWSClient).elbv2conn
96+
resp, err := elbconn.DescribeTargetHealth(&elbv2.DescribeTargetHealthInput{
97+
TargetGroupArn: aws.String(d.Get("target_group_arn").(string)),
98+
Targets: []*elbv2.TargetDescription{
99+
{
100+
Id: aws.String(d.Get("target_id").(string)),
101+
Port: aws.Int64(int64(d.Get("port").(int))),
102+
},
103+
},
104+
})
105+
if err != nil {
106+
if isTargetGroupNotFound(err) {
107+
log.Printf("[WARN] Target group does not exist, removing target attachment %s", d.Id())
108+
d.SetId("")
109+
return nil
110+
}
111+
if isInvalidTarget(err) {
112+
log.Printf("[WARN] Target does not exist, removing target attachment %s", d.Id())
113+
d.SetId("")
114+
return nil
115+
}
116+
return errwrap.Wrapf("Error reading Target Health: {{err}}", err)
117+
}
118+
119+
if len(resp.TargetHealthDescriptions) != 1 {
120+
log.Printf("[WARN] Target does not exist, removing target attachment %s", d.Id())
121+
d.SetId("")
122+
return nil
123+
}
124+
125+
return nil
126+
}
127+
128+
func isInvalidTarget(err error) bool {
129+
elberr, ok := err.(awserr.Error)
130+
return ok && elberr.Code() == "InvalidTarget"
131+
}
Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
package aws
2+
3+
import (
4+
"errors"
5+
"fmt"
6+
"github.com/aws/aws-sdk-go/aws"
7+
"github.com/aws/aws-sdk-go/service/elbv2"
8+
"github.com/hashicorp/errwrap"
9+
"github.com/hashicorp/terraform/helper/acctest"
10+
"github.com/hashicorp/terraform/helper/resource"
11+
"github.com/hashicorp/terraform/terraform"
12+
"strconv"
13+
"testing"
14+
)
15+
16+
func TestAccAWSALBTargetGroupAttachment_basic(t *testing.T) {
17+
targetGroupName := fmt.Sprintf("test-target-group-%s", acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum))
18+
19+
resource.Test(t, resource.TestCase{
20+
PreCheck: func() { testAccPreCheck(t) },
21+
IDRefreshName: "aws_alb_target_group.test",
22+
Providers: testAccProviders,
23+
CheckDestroy: testAccCheckAWSALBTargetGroupAttachmentDestroy,
24+
Steps: []resource.TestStep{
25+
{
26+
Config: testAccAWSALBTargetGroupAttachmentConfig_basic(targetGroupName),
27+
Check: resource.ComposeAggregateTestCheckFunc(
28+
testAccCheckAWSALBTargetGroupAttachmentExists("aws_alb_target_group_attachment.test"),
29+
),
30+
},
31+
},
32+
})
33+
}
34+
35+
func testAccCheckAWSALBTargetGroupAttachmentExists(n string) resource.TestCheckFunc {
36+
return func(s *terraform.State) error {
37+
rs, ok := s.RootModule().Resources[n]
38+
if !ok {
39+
return fmt.Errorf("Not found: %s", n)
40+
}
41+
42+
if rs.Primary.ID == "" {
43+
return errors.New("No Target Group Attachment ID is set")
44+
}
45+
46+
conn := testAccProvider.Meta().(*AWSClient).elbv2conn
47+
48+
port, _ := strconv.Atoi(rs.Primary.Attributes["port"])
49+
describe, err := conn.DescribeTargetHealth(&elbv2.DescribeTargetHealthInput{
50+
TargetGroupArn: aws.String(rs.Primary.Attributes["target_group_arn"]),
51+
Targets: []*elbv2.TargetDescription{
52+
{
53+
Id: aws.String(rs.Primary.Attributes["target_id"]),
54+
Port: aws.Int64(int64(port)),
55+
},
56+
},
57+
})
58+
59+
if err != nil {
60+
return err
61+
}
62+
63+
if len(describe.TargetHealthDescriptions) != 1 {
64+
return errors.New("Target Group Attachment not found")
65+
}
66+
67+
return nil
68+
}
69+
}
70+
71+
func testAccCheckAWSALBTargetGroupAttachmentDestroy(s *terraform.State) error {
72+
conn := testAccProvider.Meta().(*AWSClient).elbv2conn
73+
74+
for _, rs := range s.RootModule().Resources {
75+
if rs.Type != "aws_alb_target_group_attachment" {
76+
continue
77+
}
78+
79+
port, _ := strconv.Atoi(rs.Primary.Attributes["port"])
80+
describe, err := conn.DescribeTargetHealth(&elbv2.DescribeTargetHealthInput{
81+
TargetGroupArn: aws.String(rs.Primary.Attributes["target_group_arn"]),
82+
Targets: []*elbv2.TargetDescription{
83+
{
84+
Id: aws.String(rs.Primary.Attributes["target_id"]),
85+
Port: aws.Int64(int64(port)),
86+
},
87+
},
88+
})
89+
if err == nil {
90+
if len(describe.TargetHealthDescriptions) != 0 {
91+
return fmt.Errorf("Target Group Attachment %q still exists", rs.Primary.ID)
92+
}
93+
}
94+
95+
// Verify the error
96+
if isTargetGroupNotFound(err) || isInvalidTarget(err) {
97+
return nil
98+
} else {
99+
return errwrap.Wrapf("Unexpected error checking ALB destroyed: {{err}}", err)
100+
}
101+
}
102+
103+
return nil
104+
}
105+
106+
func testAccAWSALBTargetGroupAttachmentConfig_basic(targetGroupName string) string {
107+
return fmt.Sprintf(`
108+
resource "aws_alb_target_group_attachment" "test" {
109+
target_group_arn = "${aws_alb_target_group.test.arn}"
110+
target_id = "${aws_instance.test.id}"
111+
port = 80
112+
}
113+
114+
resource "aws_instance" "test" {
115+
ami = "ami-f701cb97"
116+
instance_type = "t2.micro"
117+
subnet_id = "${aws_subnet.subnet.id}"
118+
}
119+
120+
resource "aws_alb_target_group" "test" {
121+
name = "%s"
122+
port = 443
123+
protocol = "HTTPS"
124+
vpc_id = "${aws_vpc.test.id}"
125+
126+
deregistration_delay = 200
127+
128+
stickiness {
129+
type = "lb_cookie"
130+
cookie_duration = 10000
131+
}
132+
133+
health_check {
134+
path = "/health"
135+
interval = 60
136+
port = 8081
137+
protocol = "HTTP"
138+
timeout = 3
139+
healthy_threshold = 3
140+
unhealthy_threshold = 3
141+
matcher = "200-299"
142+
}
143+
}
144+
145+
resource "aws_subnet" "subnet" {
146+
cidr_block = "10.0.1.0/24"
147+
vpc_id = "${aws_vpc.test.id}"
148+
149+
}
150+
151+
resource "aws_vpc" "test" {
152+
cidr_block = "10.0.0.0/16"
153+
}`, targetGroupName)
154+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
---
2+
layout: "aws"
3+
page_title: "AWS: aws_alb_target_group_attachment"
4+
sidebar_current: "docs-aws-resource-alb-target-group-attachment"
5+
description: |-
6+
Provides the ability to register instances and containers with an ALB
7+
target group
8+
---
9+
10+
# aws\_alb\_target\_group\_attachment
11+
12+
Provides the ability to register instances and containers with an ALB
13+
target group
14+
15+
## Example Usage
16+
17+
```
18+
resource "aws_alb_target_group_attachment" "test" {
19+
target_group_arn = "${aws_alb_target_group.test.arn}"
20+
target_id = "${aws_instance.test.id}"
21+
port = 80
22+
}
23+
24+
resource "aws_alb_target_group" "test" {
25+
// Other arguments
26+
}
27+
28+
resource "aws_instance" "test" {
29+
// Other arguments
30+
}
31+
```
32+
33+
## Argument Reference
34+
35+
The following arguments are supported:
36+
37+
* `target_group_arn` - (Required) The ARN of the target group with which to register targets
38+
* `target_id` (Required) The ID of the target. This is the Instance ID for an instance, or the container ID for an ECS container.
39+
* `port` - (Required) The port on which targets receive traffic.
40+
41+
## Attributes Reference
42+
43+
The following attributes are exported in addition to the arguments listed above:
44+
45+
* `id` - A unique identifier for the attachment
46+
47+
## Import
48+
49+
Target Group Attachments cannot be imported.
50+

website/source/layouts/aws.erb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,10 @@
226226
<a href="/docs/providers/aws/r/alb_target_group.html">aws_alb_target_group</a>
227227
</li>
228228

229+
<li<%= sidebar_current("docs-aws-resource-alb-target-group-attachment") %>>
230+
<a href="/docs/providers/aws/r/alb_target_group_attachment.html">aws_alb_target_group_attachment</a>
231+
</li>
232+
229233
<li<%= sidebar_current("docs-aws-resource-ami") %>>
230234
<a href="/docs/providers/aws/r/ami.html">aws_ami</a>
231235
</li>

0 commit comments

Comments
 (0)