diff --git a/builtin/providers/dns/data_dns_a_record_set.go b/builtin/providers/dns/data_dns_a_record_set.go new file mode 100644 index 0000000000..dfdc755fe6 --- /dev/null +++ b/builtin/providers/dns/data_dns_a_record_set.go @@ -0,0 +1,52 @@ +package dns + +import ( + "fmt" + "net" + "sort" + + "github.com/hashicorp/terraform/helper/schema" +) + +func dataSourceDnsARecordSet() *schema.Resource { + return &schema.Resource{ + Read: dataSourceDnsARecordSetRead, + Schema: map[string]*schema.Schema{ + "host": &schema.Schema{ + Type: schema.TypeString, + Required: true, + }, + "addrs": &schema.Schema{ + Type: schema.TypeList, + Elem: &schema.Schema{Type: schema.TypeString}, + Computed: true, + }, + }, + } +} + +func dataSourceDnsARecordSetRead(d *schema.ResourceData, meta interface{}) error { + host := d.Get("host").(string) + + records, err := net.LookupIP(host) + if err != nil { + return fmt.Errorf("error looking up A records for %q: %s", host, err) + } + + addrs := make([]string, 0) + + for _, ip := range records { + // LookupIP returns A (IPv4) and AAAA (IPv6) records + // Filter out AAAA records + if ipv4 := ip.To4(); ipv4 != nil { + addrs = append(addrs, ipv4.String()) + } + } + + sort.Strings(addrs) + + d.Set("addrs", addrs) + d.SetId(host) + + return nil +} \ No newline at end of file diff --git a/builtin/providers/dns/data_dns_a_record_set_test.go b/builtin/providers/dns/data_dns_a_record_set_test.go new file mode 100644 index 0000000000..2052294c1a --- /dev/null +++ b/builtin/providers/dns/data_dns_a_record_set_test.go @@ -0,0 +1,53 @@ +package dns + +import ( + "fmt" + "testing" + + r "github.com/hashicorp/terraform/helper/resource" +) + +func TestAccDnsARecordSet_Basic(t *testing.T) { + tests := []struct { + DataSourceBlock string + DataSourceName string + Expected []string + }{ + { + ` + data "dns_a_record_set" "foo" { + host = "127.0.0.1.nip.io" + } + `, + "foo", + []string{ + "127.0.0.1", + }, + }, + { + ` + data "dns_a_record_set" "ntp" { + host = "time-c.nist.gov" + } + `, + "ntp", + []string{ + "129.6.15.30", + }, + }, + } + + for _, test := range tests { + r.UnitTest(t, r.TestCase{ + Providers: testAccProviders, + Steps: []r.TestStep{ + r.TestStep{ + Config: test.DataSourceBlock, + Check: r.ComposeTestCheckFunc( + testCheckAttrStringArray(fmt.Sprintf("data.dns_a_record_set.%s", test.DataSourceName), "addrs", test.Expected), + ), + }, + }, + }) + } +} diff --git a/builtin/providers/dns/data_dns_cname_record_set.go b/builtin/providers/dns/data_dns_cname_record_set.go new file mode 100644 index 0000000000..282d9846b6 --- /dev/null +++ b/builtin/providers/dns/data_dns_cname_record_set.go @@ -0,0 +1,41 @@ +package dns + +import ( + "fmt" + "net" + + "github.com/hashicorp/terraform/helper/schema" +) + +func dataSourceDnsCnameRecordSet() *schema.Resource { + return &schema.Resource{ + Read: dataSourceDnsCnameRecordSetRead, + + Schema: map[string]*schema.Schema{ + "host": &schema.Schema{ + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + + "cname": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + }, + }, + } +} + +func dataSourceDnsCnameRecordSetRead(d *schema.ResourceData, meta interface{}) error { + host := d.Get("host").(string) + + cname, err := net.LookupCNAME(host) + if err != nil { + return fmt.Errorf("error looking up CNAME records for %q: %s", host, err) + } + + d.Set("cname", cname) + d.SetId(host) + + return nil +} diff --git a/builtin/providers/dns/data_dns_cname_record_set_test.go b/builtin/providers/dns/data_dns_cname_record_set_test.go new file mode 100644 index 0000000000..84270ff04e --- /dev/null +++ b/builtin/providers/dns/data_dns_cname_record_set_test.go @@ -0,0 +1,37 @@ +package dns + +import ( + "testing" + + r "github.com/hashicorp/terraform/helper/resource" +) + +func TestAccDnsCnameRecordSet_Basic(t *testing.T) { + tests := []struct { + DataSourceBlock string + Expected string + }{ + { + ` + data "dns_cname_record_set" "foo" { + host = "www.hashicorp.com" + } + `, + "s.shared.global.fastly.net.", + }, + } + + for _, test := range tests { + r.UnitTest(t, r.TestCase{ + Providers: testAccProviders, + Steps: []r.TestStep{ + r.TestStep{ + Config: test.DataSourceBlock, + Check: r.ComposeTestCheckFunc( + r.TestCheckResourceAttr("data.dns_cname_record_set.foo", "cname", test.Expected), + ), + }, + }, + }) + } +} diff --git a/builtin/providers/dns/data_dns_txt_record_set.go b/builtin/providers/dns/data_dns_txt_record_set.go new file mode 100644 index 0000000000..67cb47e828 --- /dev/null +++ b/builtin/providers/dns/data_dns_txt_record_set.go @@ -0,0 +1,49 @@ +package dns + +import ( + "fmt" + "net" + + "github.com/hashicorp/terraform/helper/schema" +) + +func dataSourceDnsTxtRecordSet() *schema.Resource { + return &schema.Resource{ + Read: dataSourceDnsTxtRecordSetRead, + + Schema: map[string]*schema.Schema{ + "host": &schema.Schema{ + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + + "record": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + }, + + "records": &schema.Schema{ + Type: schema.TypeList, + Elem: &schema.Schema{Type: schema.TypeString}, + Computed: true, + }, + }, + } +} + +func dataSourceDnsTxtRecordSetRead(d *schema.ResourceData, meta interface{}) error { + host := d.Get("host").(string) + records, err := net.LookupTXT(host) + if err != nil { + return fmt.Errorf("error looking up TXT records for %q: %s", host, err) + } + + if len(records) > 0 { + d.Set("record", records[0]) + } else { + d.Set("record", "") + } + d.Set("records", records) + return nil +} diff --git a/builtin/providers/dns/provider.go b/builtin/providers/dns/provider.go index 785621782e..8d960dac69 100644 --- a/builtin/providers/dns/provider.go +++ b/builtin/providers/dns/provider.go @@ -49,6 +49,12 @@ func Provider() terraform.ResourceProvider { }, }, + DataSourcesMap: map[string]*schema.Resource{ + "dns_a_record_set": dataSourceDnsARecordSet(), + "dns_cname_record_set": dataSourceDnsCnameRecordSet(), + "dns_txt_record_set": dataSourceDnsTxtRecordSet(), + }, + ResourcesMap: map[string]*schema.Resource{ "dns_a_record_set": resourceDnsARecordSet(), "dns_aaaa_record_set": resourceDnsAAAARecordSet(), diff --git a/builtin/providers/dns/test_check_attr_string_array.go b/builtin/providers/dns/test_check_attr_string_array.go new file mode 100644 index 0000000000..344c7cb8de --- /dev/null +++ b/builtin/providers/dns/test_check_attr_string_array.go @@ -0,0 +1,52 @@ +package dns + +import ( + "fmt" + "strconv" + + r "github.com/hashicorp/terraform/helper/resource" + "github.com/hashicorp/terraform/terraform" +) + +func testCheckAttrStringArray(name, key string, value []string) r.TestCheckFunc { + return func(s *terraform.State) error { + ms := s.RootModule() + rs, ok := ms.Resources[name] + if !ok { + return fmt.Errorf("Not found: %s", name) + } + + is := rs.Primary + if is == nil { + return fmt.Errorf("No primary instance: %s", name) + } + + attrKey := fmt.Sprintf("%s.#", key) + count, ok := is.Attributes[attrKey] + if !ok { + return fmt.Errorf("Attributes not found for %s", attrKey) + } + + got, _ := strconv.Atoi(count) + if got != len(value) { + return fmt.Errorf("Mismatch array count for %s: got %s, wanted %d", key, count, len(value)) + } + + for i, want := range value { + attrKey = fmt.Sprintf("%s.%d", key, i) + got, ok := is.Attributes[attrKey] + if !ok { + return fmt.Errorf("Missing array item for %s", attrKey) + } + if got != want { + return fmt.Errorf( + "Mismatched array item for %s: got %s, want %s", + attrKey, + got, + want) + } + } + + return nil + } +}