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

New data sources: aws_route53_resolver_rule and aws_route53_resolver_rules #9085

Closed
wants to merge 8 commits into from
151 changes: 151 additions & 0 deletions aws/data_source_aws_route53_resolver_rule.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
package aws

import (
"fmt"
"log"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/route53resolver"
"github.com/hashicorp/terraform/helper/schema"
"github.com/hashicorp/terraform/helper/validation"
)

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 found with the id (%q)", v)
}

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
}
140 changes: 140 additions & 0 deletions aws/data_source_aws_route53_resolver_rule_test.go
Original file line number Diff line number Diff line change
@@ -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 = "%[1]s.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 = "%[1]s.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)
}
101 changes: 101 additions & 0 deletions aws/data_source_aws_route53_resolver_rules.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
package aws

import (
"fmt"
"log"
"time"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/route53resolver"
"github.com/hashicorp/terraform/helper/schema"
"github.com/hashicorp/terraform/helper/validation"
)

func dataSourceAwsRoute53ResolverRules() *schema.Resource {
return &schema.Resource{
Read: dataSourceAwsRoute53ResolverRulesRead,

Schema: map[string]*schema.Schema{
"owner_id": {
Type: schema.TypeString,
Optional: true,
ValidateFunc: validation.Any(
validateAwsAccountId,
// The owner of the default Internet Resolver rule.
validation.StringInSlice([]string{"Route 53 Resolver"}, false),
ewbankkit marked this conversation as resolved.
Show resolved Hide resolved
),
},

"resolver_endpoint_id": {
Type: schema.TypeString,
Optional: true,
},

"resolver_rule_ids": {
Type: schema.TypeSet,
Computed: true,
Elem: &schema.Schema{Type: schema.TypeString},
Set: schema.HashString,
},

"rule_type": {
Type: schema.TypeString,
Optional: true,
ValidateFunc: validation.StringInSlice([]string{
route53resolver.RuleTypeOptionForward,
route53resolver.RuleTypeOptionSystem,
route53resolver.RuleTypeOptionRecursive,
}, false),
},

"share_status": {
Type: schema.TypeString,
Optional: true,
ValidateFunc: validation.StringInSlice([]string{
route53resolver.ShareStatusNotShared,
route53resolver.ShareStatusSharedWithMe,
route53resolver.ShareStatusSharedByMe,
}, false),
},
},
}
}

func dataSourceAwsRoute53ResolverRulesRead(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).route53resolverconn

req := &route53resolver.ListResolverRulesInput{}
resolverRuleIds := []*string{}

log.Printf("[DEBUG] Listing Route53 Resolver rules: %s", req)
err := conn.ListResolverRulesPages(req, func(page *route53resolver.ListResolverRulesOutput, isLast bool) bool {
for _, rule := range page.ResolverRules {
if v, ok := d.GetOk("owner_id"); ok && aws.StringValue(rule.OwnerId) != v.(string) {
continue
}
if v, ok := d.GetOk("resolver_endpoint_id"); ok && aws.StringValue(rule.ResolverEndpointId) != v.(string) {
continue
}
if v, ok := d.GetOk("rule_type"); ok && aws.StringValue(rule.RuleType) != v.(string) {
continue
}
if v, ok := d.GetOk("share_status"); ok && aws.StringValue(rule.ShareStatus) != v.(string) {
continue
}

resolverRuleIds = append(resolverRuleIds, rule.Id)
}
return !isLast
})
if err != nil {
return fmt.Errorf("error getting Route53 Resolver rules: %s", err)
}

d.SetId(time.Now().UTC().String())
err = d.Set("resolver_rule_ids", flattenStringSet(resolverRuleIds))
if err != nil {
return fmt.Errorf("error setting resolver_rule_ids: %s", err)
}

return nil
}
Loading