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

Add a CNAME recursive resolving datasource #390

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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