Skip to content

Commit

Permalink
Add a CNAME recursive resolving datasource
Browse files Browse the repository at this point in the history
  • Loading branch information
hightoxicity committed Dec 19, 2023
1 parent 3b378d1 commit 7b93079
Show file tree
Hide file tree
Showing 5 changed files with 192 additions and 0 deletions.
36 changes: 36 additions & 0 deletions docs/data-sources/recursive_cname_record_set.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
---
# generated by https://github.com/hashicorp/terraform-plugin-docs
page_title: "dns_recursive_cname_record_set Data Source - terraform-provider-dns"
subcategory: ""
description: |-
Use this data source to get DNS CNAME record set of the host.
---

# dns_recursive_cname_record_set (Data Source)

Use this data source to get DNS CNAME record set of the host.

## Example Usage

```terraform
data "dns_recursive_cname_record_set" "hashicorp" {
host = "www.hashicorp.com"
}
output "hashi_cnames" {
value = data.dns_recursive_cname_record_set.hashicorp.cnames
}
```

<!-- schema generated by tfplugindocs -->
## Schema

### Required

- `host` (String) Host to recursively look up.

### Read-Only

- `cnames` (List of String) Chained CNAME records associated with host.
- `id` (String) Always set to the host.
- `last_cname` (String) The final CNAME at end of the chain.
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
data "dns_recursive_cname_record_set" "hashicorp" {
host = "www.hashicorp.com"
}

output "hashi_cnames" {
value = data.dns_recursive_cname_record_set.hashicorp.cnames
}
89 changes: 89 additions & 0 deletions internal/provider/data_dns_recursive_cname_record_set.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0

package provider

import (
"context"
"fmt"
"net"
"strings"

"github.com/hashicorp/terraform-plugin-framework/datasource"
"github.com/hashicorp/terraform-plugin-framework/datasource/schema"
"github.com/hashicorp/terraform-plugin-framework/types"
)

var (
_ datasource.DataSource = (*dnsCNAMERecursiveRecordSetDataSource)(nil)
)

func NewDnsCNAMERecursiveRecordSetDataSource() datasource.DataSource {
return &dnsCNAMERecursiveRecordSetDataSource{}
}

type dnsCNAMERecursiveRecordSetDataSource struct{}

func (d *dnsCNAMERecursiveRecordSetDataSource) Metadata(ctx context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) {
resp.TypeName = req.ProviderTypeName + "_recursive_cname_record_set"
}

func (d *dnsCNAMERecursiveRecordSetDataSource) Schema(ctx context.Context, req datasource.SchemaRequest, resp *datasource.SchemaResponse) {
resp.Schema = schema.Schema{
Description: "Use this data source to get DNS CNAME record set of the host.",
Attributes: map[string]schema.Attribute{
"host": schema.StringAttribute{
Required: true,
Description: "Host to recursively look up.",
},
"cnames": schema.ListAttribute{
ElementType: types.StringType,
Computed: true,
Description: "Chained CNAME records associated with host.",
},
"last_cname": schema.StringAttribute{
Computed: true,
Description: "The final CNAME at end of the chain.",
},
"id": schema.StringAttribute{
Computed: true,
Description: "Always set to the host.",
},
},
}
}

func (d *dnsCNAMERecursiveRecordSetDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) {
var config cnameRecursiveRecordSetConfig

resp.Diagnostics.Append(req.Config.Get(ctx, &config)...)
if resp.Diagnostics.HasError() {
return
}

cnames := []string{}

host := config.Host.ValueString()
for cname, err := net.LookupCNAME(host); cname != host; cname, err = net.LookupCNAME(host) {
if err != nil {
resp.Diagnostics.AddError(fmt.Sprintf("error looking up CNAME records for %q: ", host), err.Error())
return
}
cnames = append(cnames, strings.Clone(cname))
host = cname
}

config.CNAMES, _ = types.ListValueFrom(ctx, types.StringType, cnames)
if len(cnames) > 0 {
config.LastCNAME = types.StringValue(cnames[len(cnames)-1])
}
config.ID = config.Host
resp.Diagnostics.Append(resp.State.Set(ctx, config)...)
}

type cnameRecursiveRecordSetConfig struct {
ID types.String `tfsdk:"id"`
Host types.String `tfsdk:"host"`
CNAMES types.List `tfsdk:"cnames"`
LastCNAME types.String `tfsdk:"last_cname"`
}
59 changes: 59 additions & 0 deletions internal/provider/data_dns_recursive_cname_record_set_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0

package provider

import (
"testing"

"github.com/hashicorp/terraform-plugin-testing/helper/resource"
)

func TestAccDataDnsRecursiveCnameRecordSet_Basic(t *testing.T) {
recordName := "data.dns_recursive_cname_record_set.test"

resource.UnitTest(t, resource.TestCase{
ProtoV5ProviderFactories: testProtoV5ProviderFactories,
Steps: []resource.TestStep{
{
Config: `
data "dns_recursive_cname_record_set" "test" {
host = "terraform-provider-dns-cname.hashicorptest.com"
}
`,
Check: resource.ComposeAggregateTestCheckFunc(
resource.TestCheckResourceAttr(recordName, "cnames.0", "example.com."),
resource.TestCheckNoResourceAttr(recordName, "cnames.1"),
resource.TestCheckResourceAttr(recordName, "last_cname", "example.com."),
resource.TestCheckResourceAttr(recordName, "host", "terraform-provider-dns-cname.hashicorptest.com"),
resource.TestCheckResourceAttr(recordName, "id", "terraform-provider-dns-cname.hashicorptest.com"),
),
},
},
})
}

func TestAccDataDnsRecursiveCnameRecordSet_Complex(t *testing.T) {
recordName := "data.dns_recursive_cname_record_set.test"

resource.UnitTest(t, resource.TestCase{
ProtoV5ProviderFactories: testProtoV5ProviderFactories,
Steps: []resource.TestStep{
{
Config: `
data "dns_recursive_cname_record_set" "test" {
host = "test2.tony.docusign.dev"
}
`,
Check: resource.ComposeAggregateTestCheckFunc(
resource.TestCheckResourceAttr(recordName, "cnames.0", "stage.services.docusign.net."),
resource.TestCheckResourceAttr(recordName, "cnames.1", "stage.services.docusign.net.akadns.net."),
resource.TestCheckNoResourceAttr(recordName, "cnames.2"),
resource.TestCheckResourceAttr(recordName, "last_cname", "stage.services.docusign.net.akadns.net."),
resource.TestCheckResourceAttr(recordName, "host", "test2.tony.docusign.dev"),
resource.TestCheckResourceAttr(recordName, "id", "test2.tony.docusign.dev"),
),
},
},
})
}
1 change: 1 addition & 0 deletions internal/provider/provider_framework.go
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,7 @@ func (p *dnsProvider) DataSources(ctx context.Context) []func() datasource.DataS
NewDnsARecordSetDataSource,
NewDnsAAAARecordSetDataSource,
NewDnsCNAMERecordSetDataSource,
NewDnsCNAMERecursiveRecordSetDataSource,
NewDnsMXRecordSetDataSource,
NewDnsNSRecordSetDataSource,
NewDnsPTRRecordSetDataSource,
Expand Down

0 comments on commit 7b93079

Please sign in to comment.