diff --git a/docs/data-sources/cname_record_set.md b/docs/data-sources/cname_record_set.md index 5ad6c476..26e9c85c 100644 --- a/docs/data-sources/cname_record_set.md +++ b/docs/data-sources/cname_record_set.md @@ -33,3 +33,4 @@ output "hashi_cname" { - `cname` (String) A CNAME record associated with host. - `id` (String) Always set to the host. +- `cname_tree` (List of String) All pieces of a CNAME tree recursively resolved. diff --git a/internal/provider/data_dns_cname_record_set.go b/internal/provider/data_dns_cname_record_set.go index bb0204bf..5a55f991 100644 --- a/internal/provider/data_dns_cname_record_set.go +++ b/internal/provider/data_dns_cname_record_set.go @@ -7,6 +7,7 @@ import ( "context" "fmt" "net" + "strings" "github.com/hashicorp/terraform-plugin-framework/datasource" "github.com/hashicorp/terraform-plugin-framework/datasource/schema" @@ -39,6 +40,11 @@ func (d *dnsCNAMERecordSetDataSource) Schema(ctx context.Context, req datasource Computed: true, Description: "A CNAME record associated with host.", }, + "cname_tree": schema.ListAttribute{ + ElementType: types.StringType, + Computed: true, + Description: "Recursively found CNAME records", + }, "id": schema.StringAttribute{ Computed: true, Description: "Always set to the host.", @@ -62,8 +68,23 @@ func (d *dnsCNAMERecordSetDataSource) Read(ctx context.Context, req datasource.R return } - config.CNAME = types.StringValue(cname) + firstLevelCname := strings.Clone(cname) + + cnameTree := []string{} + + for host != cname { + cnameTree = append(cnameTree, host) + host = strings.Clone(cname) + cname, err = net.LookupCNAME(host) + if err != nil { + resp.Diagnostics.AddError(fmt.Sprintf("error looking up CNAME records for %q: ", host), err.Error()) + return + } + } + + config.CNAME = types.StringValue(firstLevelCname) config.ID = config.Host + config.Tree, _ = types.ListValueFrom(ctx, types.StringType, cnameTree) resp.Diagnostics.Append(resp.State.Set(ctx, config)...) } @@ -71,4 +92,5 @@ type cnameRecordSetConfig struct { ID types.String `tfsdk:"id"` Host types.String `tfsdk:"host"` CNAME types.String `tfsdk:"cname"` + Tree types.List `tfsdk:"cname_tree"` } diff --git a/internal/provider/data_dns_cname_record_set_test.go b/internal/provider/data_dns_cname_record_set_test.go index 2acdab1f..283015de 100644 --- a/internal/provider/data_dns_cname_record_set_test.go +++ b/internal/provider/data_dns_cname_record_set_test.go @@ -24,6 +24,30 @@ data "dns_cname_record_set" "test" { Check: resource.ComposeAggregateTestCheckFunc( resource.TestCheckResourceAttr(recordName, "cname", "example.com."), resource.TestCheckResourceAttr(recordName, "id", "terraform-provider-dns-cname.hashicorptest.com"), + resource.TestCheckResourceAttr(recordName, "cname_tree.0", "terraform-provider-dns-cname.hashicorptest.com"), + ), + }, + }, + }) +} + +func TestAccDataDnsCnameRecordSet_Advanced(t *testing.T) { + recordName := "data.dns_cname_record_set.test" + + resource.UnitTest(t, resource.TestCase{ + ProtoV5ProviderFactories: testProtoV5ProviderFactories, + Steps: []resource.TestStep{ + { + Config: ` +data "dns_cname_record_set" "test" { + host = "test2.tony.docusign.dev" +} +`, + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr(recordName, "cname", "stage.services.docusign.net."), + resource.TestCheckResourceAttr(recordName, "id", "test2.tony.docusign.dev"), + resource.TestCheckResourceAttr(recordName, "cname_tree.0", "test2.tony.docusign.dev"), + resource.TestCheckResourceAttr(recordName, "cname_tree.1", "stage.services.docusign.net."), ), }, },