From c2bb12ce961e207c14050b1c38458d8edd5964a4 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Fri, 21 Jun 2019 17:37:40 -0400 Subject: [PATCH 1/7] Add 'aws_route53_resolver_rule' data source. --- aws/data_source_aws_route53_resolver_rule.go | 152 ++++++++++++++++++ ...a_source_aws_route53_resolver_rule_test.go | 140 ++++++++++++++++ aws/provider.go | 1 + website/aws.erb | 11 ++ .../d/route53_resolver_rule.html.markdown | 44 +++++ 5 files changed, 348 insertions(+) create mode 100644 aws/data_source_aws_route53_resolver_rule.go create mode 100644 aws/data_source_aws_route53_resolver_rule_test.go create mode 100644 website/docs/d/route53_resolver_rule.html.markdown diff --git a/aws/data_source_aws_route53_resolver_rule.go b/aws/data_source_aws_route53_resolver_rule.go new file mode 100644 index 000000000000..05283df776ba --- /dev/null +++ b/aws/data_source_aws_route53_resolver_rule.go @@ -0,0 +1,152 @@ +package aws + +import ( + "fmt" + "log" + + "github.com/hashicorp/terraform/helper/schema" + "github.com/hashicorp/terraform/helper/validation" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/service/route53resolver" +) + +func dataSourceAwsRoute53ResolverRule() *schema.Resource { + return &schema.Resource{ + Read: dataSourceAwsRoute53ResolverRuleRead, + + Schema: map[string]*schema.Schema{ + "arn": { + Type: schema.TypeString, + Computed: true, + }, + + "domain_name": { + Type: schema.TypeString, + Optional: true, + Computed: true, + ValidateFunc: validation.StringLenBetween(1, 256), + ConflictsWith: []string{"resolver_rule_id"}, + }, + + "name": { + Type: schema.TypeString, + Optional: true, + Computed: true, + ValidateFunc: validateRoute53ResolverName, + ConflictsWith: []string{"resolver_rule_id"}, + }, + + "owner_id": { + Type: schema.TypeString, + Computed: true, + }, + + "resolver_endpoint_id": { + Type: schema.TypeString, + Optional: true, + Computed: true, + ConflictsWith: []string{"resolver_rule_id"}, + }, + + "resolver_rule_id": { + Type: schema.TypeString, + Optional: true, + Computed: true, + ConflictsWith: []string{"domain_name", "name", "resolver_endpoint_id", "rule_type"}, + }, + + "rule_type": { + Type: schema.TypeString, + Optional: true, + Computed: true, + ValidateFunc: validation.StringInSlice([]string{ + route53resolver.RuleTypeOptionForward, + route53resolver.RuleTypeOptionSystem, + route53resolver.RuleTypeOptionRecursive, + }, false), + ConflictsWith: []string{"resolver_rule_id"}, + }, + + "share_status": { + Type: schema.TypeString, + Computed: true, + }, + + "tags": tagsSchemaComputed(), + }, + } +} + +func dataSourceAwsRoute53ResolverRuleRead(d *schema.ResourceData, meta interface{}) error { + conn := meta.(*AWSClient).route53resolverconn + + var rule *route53resolver.ResolverRule + if v, ok := d.GetOk("resolver_rule_id"); ok { + ruleRaw, state, err := route53ResolverRuleRefresh(conn, v.(string))() + if err != nil { + return fmt.Errorf("error getting Route53 Resolver rule (%s): %s", v, err) + } + + if state == route53ResolverRuleStatusDeleted { + return fmt.Errorf("no Route53 Resolver rules matched") + } + + rule = ruleRaw.(*route53resolver.ResolverRule) + } else { + req := &route53resolver.ListResolverRulesInput{ + Filters: buildRoute53ResolverAttributeFilterList(map[string]string{ + "DOMAIN_NAME": d.Get("domain_name").(string), + "NAME": d.Get("name").(string), + "RESOLVER_ENDPOINT_ID": d.Get("resolver_endpoint_id").(string), + "TYPE": d.Get("rule_type").(string), + }), + } + + log.Printf("[DEBUG] Listing Route53 Resolver rules: %s", req) + resp, err := conn.ListResolverRules(req) + if err != nil { + return fmt.Errorf("error getting Route53 Resolver rules: %s", err) + } + + if n := len(resp.ResolverRules); n == 0 { + return fmt.Errorf("no Route53 Resolver rules matched") + } else if n > 1 { + return fmt.Errorf("%d Route53 Resolver rules matched; use additional constraints to reduce matches to a rule", n) + } + + rule = resp.ResolverRules[0] + } + + d.SetId(aws.StringValue(rule.Id)) + d.Set("arn", rule.Arn) + d.Set("domain_name", rule.DomainName) + d.Set("name", rule.Name) + d.Set("owner_id", rule.OwnerId) + d.Set("resolver_endpoint_id", rule.ResolverEndpointId) + d.Set("resolver_rule_id", rule.Id) + d.Set("rule_type", rule.RuleType) + d.Set("share_status", rule.ShareStatus) + if err := getTagsRoute53Resolver(conn, d); err != nil { + return fmt.Errorf("error reading Route 53 Resolver rule (%s) tags: %s", d.Id(), err) + } + + return nil +} + +func buildRoute53ResolverAttributeFilterList(attrs map[string]string) []*route53resolver.Filter { + filters := []*route53resolver.Filter{} + + for k, v := range attrs { + if v == "" { + continue + } + + filters = append(filters, &route53resolver.Filter{ + Name: aws.String(k), + Values: aws.StringSlice([]string{v}), + }) + } + + return filters +} diff --git a/aws/data_source_aws_route53_resolver_rule_test.go b/aws/data_source_aws_route53_resolver_rule_test.go new file mode 100644 index 000000000000..ad26e8d21f8b --- /dev/null +++ b/aws/data_source_aws_route53_resolver_rule_test.go @@ -0,0 +1,140 @@ +package aws + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform/helper/acctest" + "github.com/hashicorp/terraform/helper/resource" +) + +func TestAccDataSourceAwsRoute53ResolverRule_basic(t *testing.T) { + rName := fmt.Sprintf("tf-testacc-r53-resolver-%s", acctest.RandStringFromCharSet(8, acctest.CharSetAlphaNum)) + resourceName := "aws_route53_resolver_rule.example" + ds1ResourceName := "data.aws_route53_resolver_rule.by_resolver_rule_id" + ds2ResourceName := "data.aws_route53_resolver_rule.by_domain_name" + ds3ResourceName := "data.aws_route53_resolver_rule.by_name_and_rule_type" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t); testAccPreCheckAWSRoute53Resolver(t) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccDataSourceAwsRoute53ResolverRule_basic(rName), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrPair(ds1ResourceName, "id", resourceName, "id"), + resource.TestCheckResourceAttrPair(ds1ResourceName, "arn", resourceName, "arn"), + resource.TestCheckResourceAttrPair(ds1ResourceName, "domain_name", resourceName, "domain_name"), + resource.TestCheckResourceAttrPair(ds1ResourceName, "name", resourceName, "name"), + resource.TestCheckResourceAttrPair(ds1ResourceName, "owner_id", resourceName, "owner_id"), + resource.TestCheckResourceAttrPair(ds1ResourceName, "resolver_endpoint_id", resourceName, "resolver_endpoint_id"), + resource.TestCheckResourceAttrPair(ds1ResourceName, "resolver_rule_id", resourceName, "id"), + resource.TestCheckResourceAttrPair(ds1ResourceName, "rule_type", resourceName, "rule_type"), + resource.TestCheckResourceAttrPair(ds1ResourceName, "share_status", resourceName, "share_status"), + resource.TestCheckResourceAttrPair(ds1ResourceName, "tags.%", resourceName, "tags.%"), + + resource.TestCheckResourceAttrPair(ds2ResourceName, "id", resourceName, "id"), + resource.TestCheckResourceAttrPair(ds2ResourceName, "arn", resourceName, "arn"), + resource.TestCheckResourceAttrPair(ds2ResourceName, "domain_name", resourceName, "domain_name"), + resource.TestCheckResourceAttrPair(ds2ResourceName, "name", resourceName, "name"), + resource.TestCheckResourceAttrPair(ds2ResourceName, "owner_id", resourceName, "owner_id"), + resource.TestCheckResourceAttrPair(ds2ResourceName, "resolver_endpoint_id", resourceName, "resolver_endpoint_id"), + resource.TestCheckResourceAttrPair(ds2ResourceName, "resolver_rule_id", resourceName, "id"), + resource.TestCheckResourceAttrPair(ds2ResourceName, "rule_type", resourceName, "rule_type"), + resource.TestCheckResourceAttrPair(ds2ResourceName, "share_status", resourceName, "share_status"), + resource.TestCheckResourceAttrPair(ds2ResourceName, "tags.%", resourceName, "tags.%"), + + resource.TestCheckResourceAttrPair(ds3ResourceName, "id", resourceName, "id"), + resource.TestCheckResourceAttrPair(ds3ResourceName, "arn", resourceName, "arn"), + resource.TestCheckResourceAttrPair(ds3ResourceName, "domain_name", resourceName, "domain_name"), + resource.TestCheckResourceAttrPair(ds3ResourceName, "name", resourceName, "name"), + resource.TestCheckResourceAttrPair(ds3ResourceName, "owner_id", resourceName, "owner_id"), + resource.TestCheckResourceAttrPair(ds3ResourceName, "resolver_endpoint_id", resourceName, "resolver_endpoint_id"), + resource.TestCheckResourceAttrPair(ds3ResourceName, "resolver_rule_id", resourceName, "id"), + resource.TestCheckResourceAttrPair(ds3ResourceName, "rule_type", resourceName, "rule_type"), + resource.TestCheckResourceAttrPair(ds3ResourceName, "share_status", resourceName, "share_status"), + resource.TestCheckResourceAttrPair(ds3ResourceName, "tags.%", resourceName, "tags.%"), + ), + }, + }, + }) +} + +func TestAccDataSourceAwsRoute53ResolverRule_ResolverEndpointIdWithTags(t *testing.T) { + rName := fmt.Sprintf("tf-testacc-r53-resolver-%s", acctest.RandStringFromCharSet(8, acctest.CharSetAlphaNum)) + resourceName := "aws_route53_resolver_rule.example" + ds1ResourceName := "data.aws_route53_resolver_rule.by_resolver_endpoint_id" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t); testAccPreCheckAWSRoute53Resolver(t) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccDataSourceAwsRoute53ResolverRule_resolverEndpointIdWithTags(rName), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrPair(ds1ResourceName, "id", resourceName, "id"), + resource.TestCheckResourceAttrPair(ds1ResourceName, "arn", resourceName, "arn"), + resource.TestCheckResourceAttrPair(ds1ResourceName, "domain_name", resourceName, "domain_name"), + resource.TestCheckResourceAttrPair(ds1ResourceName, "name", resourceName, "name"), + resource.TestCheckResourceAttrPair(ds1ResourceName, "owner_id", resourceName, "owner_id"), + resource.TestCheckResourceAttrPair(ds1ResourceName, "resolver_endpoint_id", resourceName, "resolver_endpoint_id"), + resource.TestCheckResourceAttrPair(ds1ResourceName, "resolver_rule_id", resourceName, "id"), + resource.TestCheckResourceAttrPair(ds1ResourceName, "rule_type", resourceName, "rule_type"), + resource.TestCheckResourceAttrPair(ds1ResourceName, "share_status", resourceName, "share_status"), + resource.TestCheckResourceAttrPair(ds1ResourceName, "tags.%", resourceName, "tags.%"), + resource.TestCheckResourceAttr(ds1ResourceName, "tags.%", "2"), + resource.TestCheckResourceAttrPair(ds1ResourceName, "tags.Key1", resourceName, "tags.Key1"), + resource.TestCheckResourceAttrPair(ds1ResourceName, "tags.Key2", resourceName, "tags.Key2"), + ), + }, + }, + }) +} + +func testAccDataSourceAwsRoute53ResolverRule_basic(rName string) string { + return fmt.Sprintf(` +resource "aws_route53_resolver_rule" "example" { + domain_name = "example.com" + rule_type = "SYSTEM" + name = %[1]q +} + +data "aws_route53_resolver_rule" "by_resolver_rule_id" { + resolver_rule_id = "${aws_route53_resolver_rule.example.id}" +} + +data "aws_route53_resolver_rule" "by_domain_name" { + domain_name = "${aws_route53_resolver_rule.example.domain_name}" +} + +data "aws_route53_resolver_rule" "by_name_and_rule_type" { + name = "${aws_route53_resolver_rule.example.name}" + rule_type = "${aws_route53_resolver_rule.example.rule_type}" +} +`, rName) +} + +func testAccDataSourceAwsRoute53ResolverRule_resolverEndpointIdWithTags(rName string) string { + return testAccRoute53ResolverRuleConfig_resolverEndpoint(rName) + fmt.Sprintf(` +resource "aws_route53_resolver_rule" "example" { + domain_name = "example.com" + rule_type = "FORWARD" + name = %[1]q + + resolver_endpoint_id = "${aws_route53_resolver_endpoint.bar.id}" + + target_ip { + ip = "192.0.2.7" + } + + tags = { + "Key1" = "Value1" + "Key2" = "Value2" + } +} + +data "aws_route53_resolver_rule" "by_resolver_endpoint_id" { + resolver_endpoint_id = "${aws_route53_resolver_rule.example.resolver_endpoint_id}" +} +`, rName) +} diff --git a/aws/provider.go b/aws/provider.go index 802c49b1dc5d..93069ec29a9d 100644 --- a/aws/provider.go +++ b/aws/provider.go @@ -249,6 +249,7 @@ func Provider() terraform.ResourceProvider { "aws_route_table": dataSourceAwsRouteTable(), "aws_route_tables": dataSourceAwsRouteTables(), "aws_route53_delegation_set": dataSourceAwsDelegationSet(), + "aws_route53_resolver_rule": dataSourceAwsRoute53ResolverRule(), "aws_route53_zone": dataSourceAwsRoute53Zone(), "aws_s3_bucket": dataSourceAwsS3Bucket(), "aws_s3_bucket_object": dataSourceAwsS3BucketObject(), diff --git a/website/aws.erb b/website/aws.erb index eae02116af9a..1fb50ba79d8f 100644 --- a/website/aws.erb +++ b/website/aws.erb @@ -2406,6 +2406,17 @@
  • Route53 Resolver