From 6da2f0b5ec25c3dd708bd05d52baff2738f14448 Mon Sep 17 00:00:00 2001 From: aharin Date: Thu, 6 Jul 2017 13:47:14 +0100 Subject: [PATCH] Add aws_alb_target_group data source (#764) (#1037) * Add aws_alb_target_group data source (#764) * Fixed formatting issues * Fixing type in docs --- aws/data_source_aws_alb_target_group.go | 153 ++++++++++++++++ aws/data_source_aws_alb_target_group_test.go | 172 ++++++++++++++++++ aws/provider.go | 1 + aws/resource_aws_alb_target_group.go | 149 +++++++-------- website/aws.erb | 3 + website/docs/d/alb_target_group.html.markdown | 48 +++++ 6 files changed, 454 insertions(+), 72 deletions(-) create mode 100644 aws/data_source_aws_alb_target_group.go create mode 100644 aws/data_source_aws_alb_target_group_test.go create mode 100644 website/docs/d/alb_target_group.html.markdown diff --git a/aws/data_source_aws_alb_target_group.go b/aws/data_source_aws_alb_target_group.go new file mode 100644 index 00000000000..82dd8e3040c --- /dev/null +++ b/aws/data_source_aws_alb_target_group.go @@ -0,0 +1,153 @@ +package aws + +import ( + "fmt" + + "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 dataSourceAwsAlbTargetGroup() *schema.Resource { + return &schema.Resource{ + Read: dataSourceAwsAlbTargetGroupRead, + Schema: map[string]*schema.Schema{ + "arn": { + Type: schema.TypeString, + Optional: true, + Computed: true, + }, + "arn_suffix": { + Type: schema.TypeString, + Computed: true, + }, + + "name": { + Type: schema.TypeString, + Optional: true, + Computed: true, + }, + + "port": { + Type: schema.TypeInt, + Computed: true, + }, + + "protocol": { + Type: schema.TypeString, + Computed: true, + }, + + "vpc_id": { + Type: schema.TypeString, + Computed: true, + }, + + "deregistration_delay": { + Type: schema.TypeInt, + Computed: true, + }, + + "stickiness": { + Type: schema.TypeList, + Computed: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "enabled": { + Type: schema.TypeBool, + Computed: true, + }, + "type": { + Type: schema.TypeString, + Computed: true, + }, + "cookie_duration": { + Type: schema.TypeInt, + Computed: true, + }, + }, + }, + }, + + "health_check": { + Type: schema.TypeList, + Computed: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "interval": { + Type: schema.TypeInt, + Computed: true, + }, + + "path": { + Type: schema.TypeString, + Computed: true, + }, + + "port": { + Type: schema.TypeString, + Computed: true, + }, + + "protocol": { + Type: schema.TypeString, + Computed: true, + }, + + "timeout": { + Type: schema.TypeInt, + Computed: true, + }, + + "healthy_threshold": { + Type: schema.TypeInt, + Computed: true, + }, + + "matcher": { + Type: schema.TypeString, + Computed: true, + }, + + "unhealthy_threshold": { + Type: schema.TypeInt, + Computed: true, + }, + }, + }, + }, + + "tags": tagsSchemaComputed(), + }, + } +} + +func dataSourceAwsAlbTargetGroupRead(d *schema.ResourceData, meta interface{}) error { + elbconn := meta.(*AWSClient).elbv2conn + tgArn := d.Get("arn").(string) + tgName := d.Get("name").(string) + + describeTgOpts := &elbv2.DescribeTargetGroupsInput{} + switch { + case tgArn != "": + describeTgOpts.TargetGroupArns = []*string{aws.String(tgArn)} + case tgName != "": + describeTgOpts.Names = []*string{aws.String(tgName)} + } + + describeResp, err := elbconn.DescribeTargetGroups(describeTgOpts) + if err != nil { + return errwrap.Wrapf("Error retrieving ALB Target Group: {{err}}", err) + } + if len(describeResp.TargetGroups) != 1 { + return fmt.Errorf("Search returned %d results, please revise so only one is returned", len(describeResp.TargetGroups)) + } + + targetGroup := describeResp.TargetGroups[0] + + d.SetId(*targetGroup.TargetGroupArn) + return flattenAwsAlbTargetGroupResource(d, meta, targetGroup) +} diff --git a/aws/data_source_aws_alb_target_group_test.go b/aws/data_source_aws_alb_target_group_test.go new file mode 100644 index 00000000000..173fed88f16 --- /dev/null +++ b/aws/data_source_aws_alb_target_group_test.go @@ -0,0 +1,172 @@ +package aws + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform/helper/acctest" + "github.com/hashicorp/terraform/helper/resource" +) + +func TestAccDataSourceAWSALBTargetGroup_basic(t *testing.T) { + albName := fmt.Sprintf("testalb-%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) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccDataSourceAWSALBTargetGroupConfigBasic(albName, targetGroupName), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("data.aws_alb_target_group.alb_tg_test_with_arn", "name", targetGroupName), + resource.TestCheckResourceAttrSet("data.aws_alb_target_group.alb_tg_test_with_arn", "arn"), + resource.TestCheckResourceAttrSet("data.aws_alb_target_group.alb_tg_test_with_arn", "arn_suffix"), + resource.TestCheckResourceAttr("data.aws_alb_target_group.alb_tg_test_with_arn", "port", "8080"), + resource.TestCheckResourceAttr("data.aws_alb_target_group.alb_tg_test_with_arn", "protocol", "HTTP"), + resource.TestCheckResourceAttr("data.aws_alb_target_group.alb_tg_test_with_arn", "protocol", "HTTP"), + resource.TestCheckResourceAttrSet("data.aws_alb_target_group.alb_tg_test_with_arn", "vpc_id"), + resource.TestCheckResourceAttr("data.aws_alb_target_group.alb_tg_test_with_arn", "deregistration_delay", "300"), + resource.TestCheckResourceAttr("data.aws_alb_target_group.alb_tg_test_with_arn", "tags.%", "1"), + resource.TestCheckResourceAttr("data.aws_alb_target_group.alb_tg_test_with_arn", "tags.TestName", "TestAccDataSourceAWSALBTargetGroup_basic"), + resource.TestCheckResourceAttr("data.aws_alb_target_group.alb_tg_test_with_arn", "stickiness.#", "1"), + resource.TestCheckResourceAttr("data.aws_alb_target_group.alb_tg_test_with_arn", "health_check.#", "1"), + resource.TestCheckResourceAttr("data.aws_alb_target_group.alb_tg_test_with_arn", "health_check.0.path", "/health"), + resource.TestCheckResourceAttr("data.aws_alb_target_group.alb_tg_test_with_arn", "health_check.0.port", "8081"), + resource.TestCheckResourceAttr("data.aws_alb_target_group.alb_tg_test_with_arn", "health_check.0.protocol", "HTTP"), + resource.TestCheckResourceAttr("data.aws_alb_target_group.alb_tg_test_with_arn", "health_check.0.timeout", "3"), + resource.TestCheckResourceAttr("data.aws_alb_target_group.alb_tg_test_with_arn", "health_check.0.healthy_threshold", "3"), + resource.TestCheckResourceAttr("data.aws_alb_target_group.alb_tg_test_with_arn", "health_check.0.unhealthy_threshold", "3"), + resource.TestCheckResourceAttr("data.aws_alb_target_group.alb_tg_test_with_arn", "health_check.0.matcher", "200-299"), + + resource.TestCheckResourceAttr("data.aws_alb_target_group.alb_tg_test_with_name", "name", targetGroupName), + resource.TestCheckResourceAttrSet("data.aws_alb_target_group.alb_tg_test_with_name", "arn"), + resource.TestCheckResourceAttrSet("data.aws_alb_target_group.alb_tg_test_with_name", "arn_suffix"), + resource.TestCheckResourceAttr("data.aws_alb_target_group.alb_tg_test_with_name", "port", "8080"), + resource.TestCheckResourceAttr("data.aws_alb_target_group.alb_tg_test_with_name", "protocol", "HTTP"), + resource.TestCheckResourceAttrSet("data.aws_alb_target_group.alb_tg_test_with_name", "vpc_id"), + resource.TestCheckResourceAttr("data.aws_alb_target_group.alb_tg_test_with_name", "deregistration_delay", "300"), + resource.TestCheckResourceAttr("data.aws_alb_target_group.alb_tg_test_with_name", "tags.%", "1"), + resource.TestCheckResourceAttr("data.aws_alb_target_group.alb_tg_test_with_name", "tags.TestName", "TestAccDataSourceAWSALBTargetGroup_basic"), + resource.TestCheckResourceAttr("data.aws_alb_target_group.alb_tg_test_with_name", "stickiness.#", "1"), + resource.TestCheckResourceAttr("data.aws_alb_target_group.alb_tg_test_with_name", "health_check.#", "1"), + resource.TestCheckResourceAttr("data.aws_alb_target_group.alb_tg_test_with_name", "health_check.0.path", "/health"), + resource.TestCheckResourceAttr("data.aws_alb_target_group.alb_tg_test_with_name", "health_check.0.port", "8081"), + resource.TestCheckResourceAttr("data.aws_alb_target_group.alb_tg_test_with_name", "health_check.0.protocol", "HTTP"), + resource.TestCheckResourceAttr("data.aws_alb_target_group.alb_tg_test_with_name", "health_check.0.timeout", "3"), + resource.TestCheckResourceAttr("data.aws_alb_target_group.alb_tg_test_with_name", "health_check.0.healthy_threshold", "3"), + resource.TestCheckResourceAttr("data.aws_alb_target_group.alb_tg_test_with_name", "health_check.0.unhealthy_threshold", "3"), + resource.TestCheckResourceAttr("data.aws_alb_target_group.alb_tg_test_with_name", "health_check.0.matcher", "200-299"), + ), + }, + }, + }) +} + +func testAccDataSourceAWSALBTargetGroupConfigBasic(albName string, targetGroupName string) string { + return fmt.Sprintf(`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 = "TestAccDataSourceAWSALBTargetGroup_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" + } + + tags { + TestName = "TestAccDataSourceAWSALBTargetGroup_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 = "TestAccDataSourceAWSALBTargetGroup_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 = "TestAccDataSourceAWSALBTargetGroup_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 = "TestAccDataSourceAWSALBTargetGroup_basic" + } +} + +data "aws_alb_target_group" "alb_tg_test_with_arn" { + arn = "${aws_alb_target_group.test.arn}" +} + +data "aws_alb_target_group" "alb_tg_test_with_name" { + name = "${aws_alb_target_group.test.name}" +}`, albName, targetGroupName) +} diff --git a/aws/provider.go b/aws/provider.go index 434652b171c..0058a545668 100644 --- a/aws/provider.go +++ b/aws/provider.go @@ -162,6 +162,7 @@ func Provider() terraform.ResourceProvider { "aws_acm_certificate": dataSourceAwsAcmCertificate(), "aws_alb": dataSourceAwsAlb(), "aws_alb_listener": dataSourceAwsAlbListener(), + "aws_alb_target_group": dataSourceAwsAlbTargetGroup(), "aws_ami": dataSourceAwsAmi(), "aws_ami_ids": dataSourceAwsAmiIds(), "aws_autoscaling_groups": dataSourceAwsAutoscalingGroups(), diff --git a/aws/resource_aws_alb_target_group.go b/aws/resource_aws_alb_target_group.go index cd425683954..5dea1b0cc89 100644 --- a/aws/resource_aws_alb_target_group.go +++ b/aws/resource_aws_alb_target_group.go @@ -246,78 +246,7 @@ func resourceAwsAlbTargetGroupRead(d *schema.ResourceData, meta interface{}) err return fmt.Errorf("Error retrieving Target Group %q", d.Id()) } - targetGroup := resp.TargetGroups[0] - - d.Set("arn", targetGroup.TargetGroupArn) - d.Set("arn_suffix", albTargetGroupSuffixFromARN(targetGroup.TargetGroupArn)) - d.Set("name", targetGroup.TargetGroupName) - d.Set("port", targetGroup.Port) - d.Set("protocol", targetGroup.Protocol) - d.Set("vpc_id", targetGroup.VpcId) - - healthCheck := make(map[string]interface{}) - healthCheck["interval"] = *targetGroup.HealthCheckIntervalSeconds - healthCheck["path"] = *targetGroup.HealthCheckPath - healthCheck["port"] = *targetGroup.HealthCheckPort - healthCheck["protocol"] = *targetGroup.HealthCheckProtocol - healthCheck["timeout"] = *targetGroup.HealthCheckTimeoutSeconds - healthCheck["healthy_threshold"] = *targetGroup.HealthyThresholdCount - healthCheck["unhealthy_threshold"] = *targetGroup.UnhealthyThresholdCount - healthCheck["matcher"] = *targetGroup.Matcher.HttpCode - d.Set("health_check", []interface{}{healthCheck}) - - attrResp, err := elbconn.DescribeTargetGroupAttributes(&elbv2.DescribeTargetGroupAttributesInput{ - TargetGroupArn: aws.String(d.Id()), - }) - if err != nil { - return errwrap.Wrapf("Error retrieving Target Group Attributes: {{err}}", err) - } - - stickinessMap := map[string]interface{}{} - for _, attr := range attrResp.Attributes { - switch *attr.Key { - case "stickiness.enabled": - enabled, err := strconv.ParseBool(*attr.Value) - if err != nil { - return fmt.Errorf("Error converting stickiness.enabled to bool: %s", *attr.Value) - } - stickinessMap["enabled"] = enabled - case "stickiness.type": - stickinessMap["type"] = *attr.Value - case "stickiness.lb_cookie.duration_seconds": - duration, err := strconv.Atoi(*attr.Value) - if err != nil { - return fmt.Errorf("Error converting stickiness.lb_cookie.duration_seconds to int: %s", *attr.Value) - } - stickinessMap["cookie_duration"] = duration - case "deregistration_delay.timeout_seconds": - timeout, err := strconv.Atoi(*attr.Value) - if err != nil { - return fmt.Errorf("Error converting deregistration_delay.timeout_seconds to int: %s", *attr.Value) - } - d.Set("deregistration_delay", timeout) - } - } - - if err := d.Set("stickiness", []interface{}{stickinessMap}); err != nil { - return err - } - - tagsResp, err := elbconn.DescribeTags(&elbv2.DescribeTagsInput{ - ResourceArns: []*string{aws.String(d.Id())}, - }) - if err != nil { - return errwrap.Wrapf("Error retrieving Target Group Tags: {{err}}", err) - } - for _, t := range tagsResp.TagDescriptions { - if *t.ResourceArn == d.Id() { - if err := d.Set("tags", tagsToMapELBv2(t.Tags)); err != nil { - return err - } - } - } - - return nil + return flattenAwsAlbTargetGroupResource(d, meta, resp.TargetGroups[0]) } func resourceAwsAlbTargetGroupUpdate(d *schema.ResourceData, meta interface{}) error { @@ -536,3 +465,79 @@ func albTargetGroupSuffixFromARN(arn *string) string { return "" } + +// flattenAwsAlbTargetGroupResource takes a *elbv2.TargetGroup and populates all respective resource fields. +func flattenAwsAlbTargetGroupResource(d *schema.ResourceData, meta interface{}, targetGroup *elbv2.TargetGroup) error { + elbconn := meta.(*AWSClient).elbv2conn + + d.Set("arn", targetGroup.TargetGroupArn) + d.Set("arn_suffix", albTargetGroupSuffixFromARN(targetGroup.TargetGroupArn)) + d.Set("name", targetGroup.TargetGroupName) + d.Set("port", targetGroup.Port) + d.Set("protocol", targetGroup.Protocol) + d.Set("vpc_id", targetGroup.VpcId) + + healthCheck := make(map[string]interface{}) + healthCheck["interval"] = *targetGroup.HealthCheckIntervalSeconds + healthCheck["path"] = *targetGroup.HealthCheckPath + healthCheck["port"] = *targetGroup.HealthCheckPort + healthCheck["protocol"] = *targetGroup.HealthCheckProtocol + healthCheck["timeout"] = *targetGroup.HealthCheckTimeoutSeconds + healthCheck["healthy_threshold"] = *targetGroup.HealthyThresholdCount + healthCheck["unhealthy_threshold"] = *targetGroup.UnhealthyThresholdCount + healthCheck["matcher"] = *targetGroup.Matcher.HttpCode + d.Set("health_check", []interface{}{healthCheck}) + + attrResp, err := elbconn.DescribeTargetGroupAttributes(&elbv2.DescribeTargetGroupAttributesInput{ + TargetGroupArn: aws.String(d.Id()), + }) + if err != nil { + return errwrap.Wrapf("Error retrieving Target Group Attributes: {{err}}", err) + } + + stickinessMap := map[string]interface{}{} + for _, attr := range attrResp.Attributes { + switch *attr.Key { + case "stickiness.enabled": + enabled, err := strconv.ParseBool(*attr.Value) + if err != nil { + return fmt.Errorf("Error converting stickiness.enabled to bool: %s", *attr.Value) + } + stickinessMap["enabled"] = enabled + case "stickiness.type": + stickinessMap["type"] = *attr.Value + case "stickiness.lb_cookie.duration_seconds": + duration, err := strconv.Atoi(*attr.Value) + if err != nil { + return fmt.Errorf("Error converting stickiness.lb_cookie.duration_seconds to int: %s", *attr.Value) + } + stickinessMap["cookie_duration"] = duration + case "deregistration_delay.timeout_seconds": + timeout, err := strconv.Atoi(*attr.Value) + if err != nil { + return fmt.Errorf("Error converting deregistration_delay.timeout_seconds to int: %s", *attr.Value) + } + d.Set("deregistration_delay", timeout) + } + } + + if err := d.Set("stickiness", []interface{}{stickinessMap}); err != nil { + return err + } + + tagsResp, err := elbconn.DescribeTags(&elbv2.DescribeTagsInput{ + ResourceArns: []*string{aws.String(d.Id())}, + }) + if err != nil { + return errwrap.Wrapf("Error retrieving Target Group Tags: {{err}}", err) + } + for _, t := range tagsResp.TagDescriptions { + if *t.ResourceArn == d.Id() { + if err := d.Set("tags", tagsToMapELBv2(t.Tags)); err != nil { + return err + } + } + } + + return nil +} diff --git a/website/aws.erb b/website/aws.erb index 37c6dd950d2..52bca3bf926 100644 --- a/website/aws.erb +++ b/website/aws.erb @@ -23,6 +23,9 @@ > aws_alb_listener + > + aws_alb_target_group + > aws_ami diff --git a/website/docs/d/alb_target_group.html.markdown b/website/docs/d/alb_target_group.html.markdown new file mode 100644 index 00000000000..88405c8fb2b --- /dev/null +++ b/website/docs/d/alb_target_group.html.markdown @@ -0,0 +1,48 @@ +--- +layout: "aws" +page_title: "AWS: aws_alb_target_group" +sidebar_current: "docs-aws-datasource-alb-target-group" +description: |- + Provides an Application Load Balancer Target Group data source. +--- + +# aws\_alb\_target\_group + +Provides information about an Application Load Balancer Target Group. + +This data source can prove useful when a module accepts an ALB Target Group as an +input variable and needs to know its attributes. It can also be used to get the ARN of +an ALB Target Group for use in other resources, given ALB Target Group name. + +## Example Usage + +```hcl +variable "alb_tg_arn" { + type = "string" + default = "" +} + +variable "alb_tg_name" { + type = "string" + default = "" +} + +data "aws_alb_target_group" "test" { + arn = "${var.alb_tg_arn}" + name = "${var.alb_tg_name}" +} +``` + +## Argument Reference + +The following arguments are supported: + +* `arn` - (Optional) The full ARN of the target group. +* `name` - (Optional) The unique name of the target group. + +~> **NOTE**: When both `arn` and `name` are specified, `arn` takes precedence. + +## Attributes Reference + +See the [ALB Target Group Resource](/docs/providers/aws/r/alb_target_group.html) for details +on the returned attributes - they are identical.