diff --git a/Godeps/Godeps.json b/Godeps/Godeps.json index 968e2def1..4b0ed4388 100644 --- a/Godeps/Godeps.json +++ b/Godeps/Godeps.json @@ -526,15 +526,15 @@ }, { "ImportPath": "github.com/jen20/riviera/azure", - "Rev": "ad1009032a2ff80c3d6ea094be49a2e98929a42b" + "Rev": "5bae671a2903c37b4d580f24d9ab74ada633813f" }, { "ImportPath": "github.com/jen20/riviera/dns", - "Rev": "ad1009032a2ff80c3d6ea094be49a2e98929a42b" + "Rev": "5bae671a2903c37b4d580f24d9ab74ada633813f" }, { "ImportPath": "github.com/jen20/riviera/sql", - "Rev": "ad1009032a2ff80c3d6ea094be49a2e98929a42b" + "Rev": "5bae671a2903c37b4d580f24d9ab74ada633813f" }, { "ImportPath": "github.com/jmespath/go-jmespath", diff --git a/builtin/providers/azurerm/provider.go b/builtin/providers/azurerm/provider.go index d19344979..dbb65ac61 100644 --- a/builtin/providers/azurerm/provider.go +++ b/builtin/providers/azurerm/provider.go @@ -64,6 +64,10 @@ func Provider() terraform.ResourceProvider { "azurerm_dns_a_record": resourceArmDnsARecord(), "azurerm_dns_aaaa_record": resourceArmDnsAAAARecord(), "azurerm_dns_cname_record": resourceArmDnsCNameRecord(), + "azurerm_dns_txt_record": resourceArmDnsTxtRecord(), + "azurerm_dns_ns_record": resourceArmDnsNsRecord(), + "azurerm_dns_mx_record": resourceArmDnsMxRecord(), + "azurerm_dns_srv_record": resourceArmDnsSrvRecord(), "azurerm_sql_server": resourceArmSqlServer(), "azurerm_sql_database": resourceArmSqlDatabase(), }, diff --git a/builtin/providers/azurerm/resource_arm_dns_mx_record.go b/builtin/providers/azurerm/resource_arm_dns_mx_record.go new file mode 100644 index 000000000..ec601f166 --- /dev/null +++ b/builtin/providers/azurerm/resource_arm_dns_mx_record.go @@ -0,0 +1,212 @@ +package azurerm + +import ( + "bytes" + "fmt" + "log" + + "github.com/hashicorp/terraform/helper/hashcode" + "github.com/hashicorp/terraform/helper/schema" + "github.com/jen20/riviera/dns" +) + +func resourceArmDnsMxRecord() *schema.Resource { + return &schema.Resource{ + Create: resourceArmDnsMxRecordCreate, + Read: resourceArmDnsMxRecordRead, + Update: resourceArmDnsMxRecordCreate, + Delete: resourceArmDnsMxRecordDelete, + + Schema: map[string]*schema.Schema{ + "name": &schema.Schema{ + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + + "resource_group_name": &schema.Schema{ + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + + "zone_name": &schema.Schema{ + Type: schema.TypeString, + Required: true, + }, + + "record": &schema.Schema{ + Type: schema.TypeSet, + Required: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "preference": &schema.Schema{ + Type: schema.TypeString, + Required: true, + }, + + "exchange": &schema.Schema{ + Type: schema.TypeString, + Required: true, + }, + }, + }, + Set: resourceArmDnsMxRecordHash, + }, + + "ttl": &schema.Schema{ + Type: schema.TypeInt, + Required: true, + }, + + "tags": tagsSchema(), + }, + } +} + +func resourceArmDnsMxRecordCreate(d *schema.ResourceData, meta interface{}) error { + client := meta.(*ArmClient) + rivieraClient := client.rivieraClient + + tags := d.Get("tags").(map[string]interface{}) + expandedTags := expandTags(tags) + + createCommand := &dns.CreateMXRecordSet{ + Name: d.Get("name").(string), + Location: "global", + ResourceGroupName: d.Get("resource_group_name").(string), + ZoneName: d.Get("zone_name").(string), + TTL: d.Get("ttl").(int), + Tags: *expandedTags, + } + + mxRecords, recordErr := expandAzureRmDnsMxRecord(d) + if recordErr != nil { + return fmt.Errorf("Error Building Azure RM MX Record: %s", recordErr) + } + createCommand.MXRecords = mxRecords + + createRequest := rivieraClient.NewRequest() + createRequest.Command = createCommand + + createResponse, err := createRequest.Execute() + if err != nil { + return fmt.Errorf("Error creating DNS MX Record: %s", err) + } + if !createResponse.IsSuccessful() { + return fmt.Errorf("Error creating DNS MX Record: %s", createResponse.Error) + } + + readRequest := rivieraClient.NewRequest() + readRequest.Command = &dns.GetMXRecordSet{ + Name: d.Get("name").(string), + ResourceGroupName: d.Get("resource_group_name").(string), + ZoneName: d.Get("zone_name").(string), + } + + readResponse, err := readRequest.Execute() + if err != nil { + return fmt.Errorf("Error reading DNS MX Record: %s", err) + } + if !readResponse.IsSuccessful() { + return fmt.Errorf("Error reading DNS MX Record: %s", readResponse.Error) + } + + resp := readResponse.Parsed.(*dns.GetMXRecordSetResponse) + d.SetId(resp.ID) + + return resourceArmDnsMxRecordRead(d, meta) +} + +func resourceArmDnsMxRecordRead(d *schema.ResourceData, meta interface{}) error { + client := meta.(*ArmClient) + rivieraClient := client.rivieraClient + + readRequest := rivieraClient.NewRequestForURI(d.Id()) + readRequest.Command = &dns.GetMXRecordSet{} + + readResponse, err := readRequest.Execute() + if err != nil { + return fmt.Errorf("Error reading DNS MX Record: %s", err) + } + if !readResponse.IsSuccessful() { + log.Printf("[INFO] Error reading DNS MX Record %q - removing from state", d.Id()) + d.SetId("") + return fmt.Errorf("Error reading DNS MX Record: %s", readResponse.Error) + } + + resp := readResponse.Parsed.(*dns.GetMXRecordSetResponse) + + d.Set("ttl", resp.TTL) + + if err := d.Set("record", flattenAzureRmDnsMxRecord(resp.MXRecords)); err != nil { + log.Printf("[INFO] Error setting the Azure RM MX Record State: %s", err) + return err + } + + flattenAndSetTags(d, &resp.Tags) + + return nil +} + +func resourceArmDnsMxRecordDelete(d *schema.ResourceData, meta interface{}) error { + client := meta.(*ArmClient) + rivieraClient := client.rivieraClient + + deleteRequest := rivieraClient.NewRequestForURI(d.Id()) + deleteRequest.Command = &dns.DeleteRecordSet{ + RecordSetType: "MX", + } + + deleteResponse, err := deleteRequest.Execute() + if err != nil { + return fmt.Errorf("Error deleting DNS MX Record: %s", err) + } + if !deleteResponse.IsSuccessful() { + return fmt.Errorf("Error deleting DNS MX Record: %s", deleteResponse.Error) + } + + return nil +} + +func expandAzureRmDnsMxRecord(d *schema.ResourceData) ([]dns.MXRecord, error) { + config := d.Get("record").(*schema.Set).List() + records := make([]dns.MXRecord, 0, len(config)) + + for _, pRaw := range config { + data := pRaw.(map[string]interface{}) + + mxrecord := dns.MXRecord{ + Preference: data["preference"].(string), + Exchange: data["exchange"].(string), + } + + records = append(records, mxrecord) + + } + + return records, nil + +} + +func flattenAzureRmDnsMxRecord(records []dns.MXRecord) []map[string]interface{} { + + result := make([]map[string]interface{}, 0, len(records)) + for _, record := range records { + result = append(result, map[string]interface{}{ + "preference": record.Preference, + "exchange": record.Exchange, + }) + } + return result + +} + +func resourceArmDnsMxRecordHash(v interface{}) int { + var buf bytes.Buffer + m := v.(map[string]interface{}) + buf.WriteString(fmt.Sprintf("%s-", m["preference"].(string))) + buf.WriteString(fmt.Sprintf("%s-", m["exchange"].(string))) + + return hashcode.String(buf.String()) +} diff --git a/builtin/providers/azurerm/resource_arm_dns_mx_record_test.go b/builtin/providers/azurerm/resource_arm_dns_mx_record_test.go new file mode 100644 index 000000000..73256ec1c --- /dev/null +++ b/builtin/providers/azurerm/resource_arm_dns_mx_record_test.go @@ -0,0 +1,267 @@ +package azurerm + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform/helper/acctest" + "github.com/hashicorp/terraform/helper/resource" + "github.com/hashicorp/terraform/terraform" + "github.com/jen20/riviera/dns" +) + +func TestAccAzureRMDnsMxRecord_basic(t *testing.T) { + ri := acctest.RandInt() + config := fmt.Sprintf(testAccAzureRMDnsMxRecord_basic, ri, ri, ri) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMDnsMxRecordDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: config, + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMDnsMxRecordExists("azurerm_dns_mx_record.test"), + ), + }, + }, + }) +} + +func TestAccAzureRMDnsMxRecord_updateRecords(t *testing.T) { + ri := acctest.RandInt() + preConfig := fmt.Sprintf(testAccAzureRMDnsMxRecord_basic, ri, ri, ri) + postConfig := fmt.Sprintf(testAccAzureRMDnsMxRecord_updateRecords, ri, ri, ri) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMDnsMxRecordDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: preConfig, + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMDnsMxRecordExists("azurerm_dns_mx_record.test"), + resource.TestCheckResourceAttr( + "azurerm_dns_mx_record.test", "record.#", "2"), + ), + }, + + resource.TestStep{ + Config: postConfig, + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMDnsMxRecordExists("azurerm_dns_mx_record.test"), + resource.TestCheckResourceAttr( + "azurerm_dns_mx_record.test", "record.#", "3"), + ), + }, + }, + }) +} + +func TestAccAzureRMDnsMxRecord_withTags(t *testing.T) { + ri := acctest.RandInt() + preConfig := fmt.Sprintf(testAccAzureRMDnsMxRecord_withTags, ri, ri, ri) + postConfig := fmt.Sprintf(testAccAzureRMDnsMxRecord_withTagsUpdate, ri, ri, ri) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMDnsMxRecordDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: preConfig, + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMDnsMxRecordExists("azurerm_dns_mx_record.test"), + resource.TestCheckResourceAttr( + "azurerm_dns_mx_record.test", "tags.#", "2"), + ), + }, + + resource.TestStep{ + Config: postConfig, + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMDnsMxRecordExists("azurerm_dns_mx_record.test"), + resource.TestCheckResourceAttr( + "azurerm_dns_mx_record.test", "tags.#", "1"), + ), + }, + }, + }) +} + +func testCheckAzureRMDnsMxRecordExists(name string) resource.TestCheckFunc { + return func(s *terraform.State) error { + // Ensure we have enough information in state to look up in API + rs, ok := s.RootModule().Resources[name] + if !ok { + return fmt.Errorf("Not found: %s", name) + } + + conn := testAccProvider.Meta().(*ArmClient).rivieraClient + + readRequest := conn.NewRequestForURI(rs.Primary.ID) + readRequest.Command = &dns.GetMXRecordSet{} + + readResponse, err := readRequest.Execute() + if err != nil { + return fmt.Errorf("Bad: GetMXRecordSet: %s", err) + } + if !readResponse.IsSuccessful() { + return fmt.Errorf("Bad: GetMXRecordSet: %s", readResponse.Error) + } + + return nil + } +} + +func testCheckAzureRMDnsMxRecordDestroy(s *terraform.State) error { + conn := testAccProvider.Meta().(*ArmClient).rivieraClient + + for _, rs := range s.RootModule().Resources { + if rs.Type != "azurerm_dns_mx_record" { + continue + } + + readRequest := conn.NewRequestForURI(rs.Primary.ID) + readRequest.Command = &dns.GetMXRecordSet{} + + readResponse, err := readRequest.Execute() + if err != nil { + return fmt.Errorf("Bad: GetMXRecordSet: %s", err) + } + + if readResponse.IsSuccessful() { + return fmt.Errorf("Bad: DNS MX Record still exists: %s", readResponse.Error) + } + } + + return nil +} + +var testAccAzureRMDnsMxRecord_basic = ` +resource "azurerm_resource_group" "test" { + name = "acctest_rg_%d" + location = "West US" +} +resource "azurerm_dns_zone" "test" { + name = "acctestzone%d.com" + resource_group_name = "${azurerm_resource_group.test.name}" +} + +resource "azurerm_dns_mx_record" "test" { + name = "myarecord%d" + resource_group_name = "${azurerm_resource_group.test.name}" + zone_name = "${azurerm_dns_zone.test.name}" + ttl = "300" + + record { + preference = "10" + exchange = "mail1.contoso.com" + } + + record { + preference = "20" + exchange = "mail2.contoso.com" + } +} +` + +var testAccAzureRMDnsMxRecord_updateRecords = ` +resource "azurerm_resource_group" "test" { + name = "acctest_rg_%d" + location = "West US" +} +resource "azurerm_dns_zone" "test" { + name = "acctestzone%d.com" + resource_group_name = "${azurerm_resource_group.test.name}" +} + +resource "azurerm_dns_mx_record" "test" { + name = "myarecord%d" + resource_group_name = "${azurerm_resource_group.test.name}" + zone_name = "${azurerm_dns_zone.test.name}" + ttl = "300" + + record { + preference = "10" + exchange = "mail1.contoso.com" + } + + record { + preference = "20" + exchange = "mail2.contoso.com" + } + + record { + preference = "50" + exchange = "mail3.contoso.com" + } +} +` + +var testAccAzureRMDnsMxRecord_withTags = ` +resource "azurerm_resource_group" "test" { + name = "acctest_rg_%d" + location = "West US" +} +resource "azurerm_dns_zone" "test" { + name = "acctestzone%d.com" + resource_group_name = "${azurerm_resource_group.test.name}" +} + +resource "azurerm_dns_mx_record" "test" { + name = "myarecord%d" + resource_group_name = "${azurerm_resource_group.test.name}" + zone_name = "${azurerm_dns_zone.test.name}" + ttl = "300" + + record { + preference = "10" + exchange = "mail1.contoso.com" + } + + record { + preference = "20" + exchange = "mail2.contoso.com" + } + + tags { + environment = "Production" + cost_center = "MSFT" + } +} +` + +var testAccAzureRMDnsMxRecord_withTagsUpdate = ` +resource "azurerm_resource_group" "test" { + name = "acctest_rg_%d" + location = "West US" +} +resource "azurerm_dns_zone" "test" { + name = "acctestzone%d.com" + resource_group_name = "${azurerm_resource_group.test.name}" +} + +resource "azurerm_dns_mx_record" "test" { + name = "myarecord%d" + resource_group_name = "${azurerm_resource_group.test.name}" + zone_name = "${azurerm_dns_zone.test.name}" + ttl = "300" + + record { + preference = "10" + exchange = "mail1.contoso.com" + } + + record { + preference = "20" + exchange = "mail2.contoso.com" + } + + tags { + environment = "staging" + } +} +` diff --git a/builtin/providers/azurerm/resource_arm_dns_ns_record.go b/builtin/providers/azurerm/resource_arm_dns_ns_record.go new file mode 100644 index 000000000..09f33d32a --- /dev/null +++ b/builtin/providers/azurerm/resource_arm_dns_ns_record.go @@ -0,0 +1,194 @@ +package azurerm + +import ( + "fmt" + "log" + + "github.com/hashicorp/terraform/helper/schema" + "github.com/jen20/riviera/dns" +) + +func resourceArmDnsNsRecord() *schema.Resource { + return &schema.Resource{ + Create: resourceArmDnsNsRecordCreate, + Read: resourceArmDnsNsRecordRead, + Update: resourceArmDnsNsRecordCreate, + Delete: resourceArmDnsNsRecordDelete, + + Schema: map[string]*schema.Schema{ + "name": &schema.Schema{ + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + + "resource_group_name": &schema.Schema{ + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + + "zone_name": &schema.Schema{ + Type: schema.TypeString, + Required: true, + }, + + "record": &schema.Schema{ + Type: schema.TypeSet, + Required: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "nsdname": &schema.Schema{ + Type: schema.TypeString, + Required: true, + }, + }, + }, + }, + + "ttl": &schema.Schema{ + Type: schema.TypeInt, + Required: true, + }, + + "tags": tagsSchema(), + }, + } +} + +func resourceArmDnsNsRecordCreate(d *schema.ResourceData, meta interface{}) error { + client := meta.(*ArmClient) + rivieraClient := client.rivieraClient + + tags := d.Get("tags").(map[string]interface{}) + expandedTags := expandTags(tags) + + createCommand := &dns.CreateNSRecordSet{ + Name: d.Get("name").(string), + Location: "global", + ResourceGroupName: d.Get("resource_group_name").(string), + ZoneName: d.Get("zone_name").(string), + TTL: d.Get("ttl").(int), + Tags: *expandedTags, + } + + nsRecords, recordErr := expandAzureRmDnsNsRecords(d) + if recordErr != nil { + return fmt.Errorf("Error Building list of Azure RM NS Records: %s", recordErr) + } + createCommand.NSRecords = nsRecords + + createRequest := rivieraClient.NewRequest() + createRequest.Command = createCommand + + createResponse, err := createRequest.Execute() + if err != nil { + return fmt.Errorf("Error creating DNS NS Record: %s", err) + } + if !createResponse.IsSuccessful() { + return fmt.Errorf("Error creating DNS NS Record: %s", createResponse.Error) + } + + readRequest := rivieraClient.NewRequest() + readRequest.Command = &dns.GetNSRecordSet{ + Name: d.Get("name").(string), + ResourceGroupName: d.Get("resource_group_name").(string), + ZoneName: d.Get("zone_name").(string), + } + + readResponse, err := readRequest.Execute() + if err != nil { + return fmt.Errorf("Error reading DNS NS Record: %s", err) + } + if !readResponse.IsSuccessful() { + return fmt.Errorf("Error reading DNS NS Record: %s", readResponse.Error) + } + + resp := readResponse.Parsed.(*dns.GetNSRecordSetResponse) + d.SetId(resp.ID) + + return resourceArmDnsNsRecordRead(d, meta) +} + +func resourceArmDnsNsRecordRead(d *schema.ResourceData, meta interface{}) error { + client := meta.(*ArmClient) + rivieraClient := client.rivieraClient + + readRequest := rivieraClient.NewRequestForURI(d.Id()) + readRequest.Command = &dns.GetNSRecordSet{} + + readResponse, err := readRequest.Execute() + if err != nil { + return fmt.Errorf("Error reading DNS Ns Record: %s", err) + } + if !readResponse.IsSuccessful() { + log.Printf("[INFO] Error reading DNS NS Record %q - removing from state", d.Id()) + d.SetId("") + return fmt.Errorf("Error reading DNS NS Record: %s", readResponse.Error) + } + + resp := readResponse.Parsed.(*dns.GetNSRecordSetResponse) + + d.Set("ttl", resp.TTL) + + if resp.NSRecords != nil { + if err := d.Set("record", flattenAzureRmDnsNsRecords(resp.NSRecords)); err != nil { + log.Printf("[INFO] Error setting the Azure RM NS Record State: %s", err) + return err + } + } + + flattenAndSetTags(d, &resp.Tags) + + return nil +} + +func resourceArmDnsNsRecordDelete(d *schema.ResourceData, meta interface{}) error { + client := meta.(*ArmClient) + rivieraClient := client.rivieraClient + + deleteRequest := rivieraClient.NewRequestForURI(d.Id()) + deleteRequest.Command = &dns.DeleteRecordSet{ + RecordSetType: "NS", + } + + deleteResponse, err := deleteRequest.Execute() + if err != nil { + return fmt.Errorf("Error deleting DNS TXT Record: %s", err) + } + if !deleteResponse.IsSuccessful() { + return fmt.Errorf("Error deleting DNS TXT Record: %s", deleteResponse.Error) + } + + return nil +} + +func expandAzureRmDnsNsRecords(d *schema.ResourceData) ([]dns.NSRecord, error) { + configs := d.Get("record").(*schema.Set).List() + nsRecords := make([]dns.NSRecord, 0, len(configs)) + + for _, configRaw := range configs { + data := configRaw.(map[string]interface{}) + + nsRecord := dns.NSRecord{ + NSDName: data["nsdname"].(string), + } + + nsRecords = append(nsRecords, nsRecord) + + } + + return nsRecords, nil + +} + +func flattenAzureRmDnsNsRecords(records []dns.NSRecord) []map[string]interface{} { + result := make([]map[string]interface{}, 0, len(records)) + for _, record := range records { + nsRecord := make(map[string]interface{}) + nsRecord["nsdname"] = record.NSDName + + result = append(result, nsRecord) + } + return result +} diff --git a/builtin/providers/azurerm/resource_arm_dns_ns_record_test.go b/builtin/providers/azurerm/resource_arm_dns_ns_record_test.go new file mode 100644 index 000000000..47994e927 --- /dev/null +++ b/builtin/providers/azurerm/resource_arm_dns_ns_record_test.go @@ -0,0 +1,257 @@ +package azurerm + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform/helper/acctest" + "github.com/hashicorp/terraform/helper/resource" + "github.com/hashicorp/terraform/terraform" + "github.com/jen20/riviera/dns" +) + +func TestAccAzureRMDnsNsRecord_basic(t *testing.T) { + ri := acctest.RandInt() + config := fmt.Sprintf(testAccAzureRMDnsNsRecord_basic, ri, ri, ri) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMDnsNsRecordDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: config, + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMDnsNsRecordExists("azurerm_dns_ns_record.test"), + ), + }, + }, + }) +} + +func TestAccAzureRMDnsNsRecord_updateRecords(t *testing.T) { + ri := acctest.RandInt() + preConfig := fmt.Sprintf(testAccAzureRMDnsNsRecord_basic, ri, ri, ri) + postConfig := fmt.Sprintf(testAccAzureRMDnsNsRecord_updateRecords, ri, ri, ri) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMDnsNsRecordDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: preConfig, + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMDnsNsRecordExists("azurerm_dns_ns_record.test"), + resource.TestCheckResourceAttr( + "azurerm_dns_ns_record.test", "record.#", "2"), + ), + }, + + resource.TestStep{ + Config: postConfig, + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMDnsNsRecordExists("azurerm_dns_ns_record.test"), + resource.TestCheckResourceAttr( + "azurerm_dns_ns_record.test", "record.#", "3"), + ), + }, + }, + }) +} + +func TestAccAzureRMDnsNsRecord_withTags(t *testing.T) { + ri := acctest.RandInt() + preConfig := fmt.Sprintf(testAccAzureRMDnsNsRecord_withTags, ri, ri, ri) + postConfig := fmt.Sprintf(testAccAzureRMDnsNsRecord_withTagsUpdate, ri, ri, ri) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMDnsNsRecordDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: preConfig, + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMDnsNsRecordExists("azurerm_dns_ns_record.test"), + resource.TestCheckResourceAttr( + "azurerm_dns_ns_record.test", "tags.#", "2"), + ), + }, + + resource.TestStep{ + Config: postConfig, + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMDnsNsRecordExists("azurerm_dns_ns_record.test"), + resource.TestCheckResourceAttr( + "azurerm_dns_ns_record.test", "tags.#", "1"), + ), + }, + }, + }) +} + +func testCheckAzureRMDnsNsRecordExists(name string) resource.TestCheckFunc { + return func(s *terraform.State) error { + // Ensure we have enough information in state to look up in API + rs, ok := s.RootModule().Resources[name] + if !ok { + return fmt.Errorf("Not found: %s", name) + } + + conn := testAccProvider.Meta().(*ArmClient).rivieraClient + + readRequest := conn.NewRequestForURI(rs.Primary.ID) + readRequest.Command = &dns.GetNSRecordSet{} + + readResponse, err := readRequest.Execute() + if err != nil { + return fmt.Errorf("Bad: GetNSRecordSet: %s", err) + } + if !readResponse.IsSuccessful() { + return fmt.Errorf("Bad: GetNSRecordSet: %s", readResponse.Error) + } + + return nil + } +} + +func testCheckAzureRMDnsNsRecordDestroy(s *terraform.State) error { + conn := testAccProvider.Meta().(*ArmClient).rivieraClient + + for _, rs := range s.RootModule().Resources { + if rs.Type != "azurerm_dns_ns_record" { + continue + } + + readRequest := conn.NewRequestForURI(rs.Primary.ID) + readRequest.Command = &dns.GetNSRecordSet{} + + readResponse, err := readRequest.Execute() + if err != nil { + return fmt.Errorf("Bad: GetNSRecordSet: %s", err) + } + + if readResponse.IsSuccessful() { + return fmt.Errorf("Bad: DNS NS Record still exists: %s", readResponse.Error) + } + } + + return nil +} + +var testAccAzureRMDnsNsRecord_basic = ` +resource "azurerm_resource_group" "test" { + name = "acctest_rg_%d" + location = "West US" +} +resource "azurerm_dns_zone" "test" { + name = "acctestzone%d.com" + resource_group_name = "${azurerm_resource_group.test.name}" +} + +resource "azurerm_dns_ns_record" "test" { + name = "myarecord%d" + resource_group_name = "${azurerm_resource_group.test.name}" + zone_name = "${azurerm_dns_zone.test.name}" + ttl = "300" + + record { + nsdname = "ns1.contoso.com" + } + + record { + nsdname = "ns2.contoso.com" + } +} +` + +var testAccAzureRMDnsNsRecord_updateRecords = ` +resource "azurerm_resource_group" "test" { + name = "acctest_rg_%d" + location = "West US" +} +resource "azurerm_dns_zone" "test" { + name = "acctestzone%d.com" + resource_group_name = "${azurerm_resource_group.test.name}" +} + +resource "azurerm_dns_ns_record" "test" { + name = "myarecord%d" + resource_group_name = "${azurerm_resource_group.test.name}" + zone_name = "${azurerm_dns_zone.test.name}" + ttl = "300" + + record { + nsdname = "ns1.contoso.com" + } + + record { + nsdname = "ns2.contoso.com" + } + + record { + nsdname = "ns3.contoso.com" + } +} +` + +var testAccAzureRMDnsNsRecord_withTags = ` +resource "azurerm_resource_group" "test" { + name = "acctest_rg_%d" + location = "West US" +} +resource "azurerm_dns_zone" "test" { + name = "acctestzone%d.com" + resource_group_name = "${azurerm_resource_group.test.name}" +} + +resource "azurerm_dns_ns_record" "test" { + name = "myarecord%d" + resource_group_name = "${azurerm_resource_group.test.name}" + zone_name = "${azurerm_dns_zone.test.name}" + ttl = "300" + + record { + nsdname = "ns1.contoso.com" + } + + record { + nsdname = "ns2.contoso.com" + } + + tags { + environment = "Production" + cost_center = "MSFT" + } +} +` + +var testAccAzureRMDnsNsRecord_withTagsUpdate = ` +resource "azurerm_resource_group" "test" { + name = "acctest_rg_%d" + location = "West US" +} +resource "azurerm_dns_zone" "test" { + name = "acctestzone%d.com" + resource_group_name = "${azurerm_resource_group.test.name}" +} + +resource "azurerm_dns_ns_record" "test" { + name = "myarecord%d" + resource_group_name = "${azurerm_resource_group.test.name}" + zone_name = "${azurerm_dns_zone.test.name}" + ttl = "300" + record { + nsdname = "ns1.contoso.com" + } + + record { + nsdname = "ns2.contoso.com" + } + + tags { + environment = "staging" + } +} +` diff --git a/builtin/providers/azurerm/resource_arm_dns_srv_record.go b/builtin/providers/azurerm/resource_arm_dns_srv_record.go new file mode 100644 index 000000000..4a2f446a0 --- /dev/null +++ b/builtin/providers/azurerm/resource_arm_dns_srv_record.go @@ -0,0 +1,228 @@ +package azurerm + +import ( + "bytes" + "fmt" + "log" + + "github.com/hashicorp/terraform/helper/hashcode" + "github.com/hashicorp/terraform/helper/schema" + "github.com/jen20/riviera/dns" +) + +func resourceArmDnsSrvRecord() *schema.Resource { + return &schema.Resource{ + Create: resourceArmDnsSrvRecordCreate, + Read: resourceArmDnsSrvRecordRead, + Update: resourceArmDnsSrvRecordCreate, + Delete: resourceArmDnsSrvRecordDelete, + + Schema: map[string]*schema.Schema{ + "name": &schema.Schema{ + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + + "resource_group_name": &schema.Schema{ + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + + "zone_name": &schema.Schema{ + Type: schema.TypeString, + Required: true, + }, + + "record": &schema.Schema{ + Type: schema.TypeSet, + Required: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "priority": &schema.Schema{ + Type: schema.TypeInt, + Required: true, + }, + + "weight": &schema.Schema{ + Type: schema.TypeInt, + Required: true, + }, + + "port": &schema.Schema{ + Type: schema.TypeInt, + Required: true, + }, + + "target": &schema.Schema{ + Type: schema.TypeString, + Required: true, + }, + }, + }, + Set: resourceArmDnsSrvRecordHash, + }, + + "ttl": &schema.Schema{ + Type: schema.TypeInt, + Required: true, + }, + + "tags": tagsSchema(), + }, + } +} + +func resourceArmDnsSrvRecordCreate(d *schema.ResourceData, meta interface{}) error { + client := meta.(*ArmClient) + rivieraClient := client.rivieraClient + + tags := d.Get("tags").(map[string]interface{}) + expandedTags := expandTags(tags) + + createCommand := &dns.CreateSRVRecordSet{ + Name: d.Get("name").(string), + Location: "global", + ResourceGroupName: d.Get("resource_group_name").(string), + ZoneName: d.Get("zone_name").(string), + TTL: d.Get("ttl").(int), + Tags: *expandedTags, + } + + srvRecords, recordErr := expandAzureRmDnsSrvRecord(d) + if recordErr != nil { + return fmt.Errorf("Error Building Azure RM SRV Record: %s", recordErr) + } + createCommand.SRVRecords = srvRecords + + createRequest := rivieraClient.NewRequest() + createRequest.Command = createCommand + + createResponse, err := createRequest.Execute() + if err != nil { + return fmt.Errorf("Error creating DNS SRV Record: %s", err) + } + if !createResponse.IsSuccessful() { + return fmt.Errorf("Error creating DNS SRV Record: %s", createResponse.Error) + } + + readRequest := rivieraClient.NewRequest() + readRequest.Command = &dns.GetSRVRecordSet{ + Name: d.Get("name").(string), + ResourceGroupName: d.Get("resource_group_name").(string), + ZoneName: d.Get("zone_name").(string), + } + + readResponse, err := readRequest.Execute() + if err != nil { + return fmt.Errorf("Error reading DNS SRV Record: %s", err) + } + if !readResponse.IsSuccessful() { + return fmt.Errorf("Error reading DNS SRV Record: %s", readResponse.Error) + } + + resp := readResponse.Parsed.(*dns.GetSRVRecordSetResponse) + d.SetId(resp.ID) + + return resourceArmDnsSrvRecordRead(d, meta) +} + +func resourceArmDnsSrvRecordRead(d *schema.ResourceData, meta interface{}) error { + client := meta.(*ArmClient) + rivieraClient := client.rivieraClient + + readRequest := rivieraClient.NewRequestForURI(d.Id()) + readRequest.Command = &dns.GetSRVRecordSet{} + + readResponse, err := readRequest.Execute() + if err != nil { + return fmt.Errorf("Error reading DNS SRV Record: %s", err) + } + if !readResponse.IsSuccessful() { + log.Printf("[INFO] Error reading DNS SRV Record %q - removing from state", d.Id()) + d.SetId("") + return fmt.Errorf("Error reading DNS SRV Record: %s", readResponse.Error) + } + + resp := readResponse.Parsed.(*dns.GetSRVRecordSetResponse) + + d.Set("ttl", resp.TTL) + + if err := d.Set("record", flattenAzureRmDnsSrvRecord(resp.SRVRecords)); err != nil { + log.Printf("[INFO] Error setting the Azure RM SRV Record State: %s", err) + return err + } + + flattenAndSetTags(d, &resp.Tags) + + return nil +} + +func resourceArmDnsSrvRecordDelete(d *schema.ResourceData, meta interface{}) error { + client := meta.(*ArmClient) + rivieraClient := client.rivieraClient + + deleteRequest := rivieraClient.NewRequestForURI(d.Id()) + deleteRequest.Command = &dns.DeleteRecordSet{ + RecordSetType: "SRV", + } + + deleteResponse, err := deleteRequest.Execute() + if err != nil { + return fmt.Errorf("Error deleting DNS SRV Record: %s", err) + } + if !deleteResponse.IsSuccessful() { + return fmt.Errorf("Error deleting DNS SRV Record: %s", deleteResponse.Error) + } + + return nil +} + +func expandAzureRmDnsSrvRecord(d *schema.ResourceData) ([]dns.SRVRecord, error) { + config := d.Get("record").(*schema.Set).List() + records := make([]dns.SRVRecord, 0, len(config)) + + for _, pRaw := range config { + data := pRaw.(map[string]interface{}) + + srvRecord := dns.SRVRecord{ + Priority: data["priority"].(int), + Weight: data["weight"].(int), + Port: data["port"].(int), + Target: data["target"].(string), + } + + records = append(records, srvRecord) + + } + + return records, nil + +} + +func flattenAzureRmDnsSrvRecord(records []dns.SRVRecord) []map[string]interface{} { + + result := make([]map[string]interface{}, 0, len(records)) + for _, record := range records { + result = append(result, map[string]interface{}{ + "priority": record.Priority, + "weight": record.Weight, + "port": record.Port, + "target": record.Target, + }) + } + return result + +} + +func resourceArmDnsSrvRecordHash(v interface{}) int { + var buf bytes.Buffer + m := v.(map[string]interface{}) + buf.WriteString(fmt.Sprintf("%d-", m["priority"].(int))) + buf.WriteString(fmt.Sprintf("%d-", m["weight"].(int))) + buf.WriteString(fmt.Sprintf("%d-", m["port"].(int))) + buf.WriteString(fmt.Sprintf("%s-", m["target"].(string))) + + return hashcode.String(buf.String()) +} diff --git a/builtin/providers/azurerm/resource_arm_dns_srv_record_test.go b/builtin/providers/azurerm/resource_arm_dns_srv_record_test.go new file mode 100644 index 000000000..d74830a68 --- /dev/null +++ b/builtin/providers/azurerm/resource_arm_dns_srv_record_test.go @@ -0,0 +1,285 @@ +package azurerm + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform/helper/acctest" + "github.com/hashicorp/terraform/helper/resource" + "github.com/hashicorp/terraform/terraform" + "github.com/jen20/riviera/dns" +) + +func TestAccAzureRMDnsSrvRecord_basic(t *testing.T) { + ri := acctest.RandInt() + config := fmt.Sprintf(testAccAzureRMDnsSrvRecord_basic, ri, ri, ri) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMDnsSrvRecordDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: config, + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMDnsSrvRecordExists("azurerm_dns_srv_record.test"), + ), + }, + }, + }) +} + +func TestAccAzureRMDnsSrvRecord_updateRecords(t *testing.T) { + ri := acctest.RandInt() + preConfig := fmt.Sprintf(testAccAzureRMDnsSrvRecord_basic, ri, ri, ri) + postConfig := fmt.Sprintf(testAccAzureRMDnsSrvRecord_updateRecords, ri, ri, ri) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMDnsSrvRecordDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: preConfig, + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMDnsSrvRecordExists("azurerm_dns_srv_record.test"), + resource.TestCheckResourceAttr( + "azurerm_dns_srv_record.test", "record.#", "2"), + ), + }, + + resource.TestStep{ + Config: postConfig, + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMDnsSrvRecordExists("azurerm_dns_srv_record.test"), + resource.TestCheckResourceAttr( + "azurerm_dns_srv_record.test", "record.#", "3"), + ), + }, + }, + }) +} + +func TestAccAzureRMDnsSrvRecord_withTags(t *testing.T) { + ri := acctest.RandInt() + preConfig := fmt.Sprintf(testAccAzureRMDnsSrvRecord_withTags, ri, ri, ri) + postConfig := fmt.Sprintf(testAccAzureRMDnsSrvRecord_withTagsUpdate, ri, ri, ri) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMDnsSrvRecordDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: preConfig, + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMDnsSrvRecordExists("azurerm_dns_srv_record.test"), + resource.TestCheckResourceAttr( + "azurerm_dns_srv_record.test", "tags.#", "2"), + ), + }, + + resource.TestStep{ + Config: postConfig, + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMDnsSrvRecordExists("azurerm_dns_srv_record.test"), + resource.TestCheckResourceAttr( + "azurerm_dns_srv_record.test", "tags.#", "1"), + ), + }, + }, + }) +} + +func testCheckAzureRMDnsSrvRecordExists(name string) resource.TestCheckFunc { + return func(s *terraform.State) error { + // Ensure we have enough information in state to look up in API + rs, ok := s.RootModule().Resources[name] + if !ok { + return fmt.Errorf("Not found: %s", name) + } + + conn := testAccProvider.Meta().(*ArmClient).rivieraClient + + readRequest := conn.NewRequestForURI(rs.Primary.ID) + readRequest.Command = &dns.GetSRVRecordSet{} + + readResponse, err := readRequest.Execute() + if err != nil { + return fmt.Errorf("Bad: GetSRVRecordSet: %s", err) + } + if !readResponse.IsSuccessful() { + return fmt.Errorf("Bad: GetSRVRecordSet: %s", readResponse.Error) + } + + return nil + } +} + +func testCheckAzureRMDnsSrvRecordDestroy(s *terraform.State) error { + conn := testAccProvider.Meta().(*ArmClient).rivieraClient + + for _, rs := range s.RootModule().Resources { + if rs.Type != "azurerm_dns_srv_record" { + continue + } + + readRequest := conn.NewRequestForURI(rs.Primary.ID) + readRequest.Command = &dns.GetSRVRecordSet{} + + readResponse, err := readRequest.Execute() + if err != nil { + return fmt.Errorf("Bad: GetSRVRecordSet: %s", err) + } + + if readResponse.IsSuccessful() { + return fmt.Errorf("Bad: DNS SRV Record still exists: %s", readResponse.Error) + } + } + + return nil +} + +var testAccAzureRMDnsSrvRecord_basic = ` +resource "azurerm_resource_group" "test" { + name = "acctest_rg_%d" + location = "West US" +} +resource "azurerm_dns_zone" "test" { + name = "acctestzone%d.com" + resource_group_name = "${azurerm_resource_group.test.name}" +} + +resource "azurerm_dns_srv_record" "test" { + name = "myarecord%d" + resource_group_name = "${azurerm_resource_group.test.name}" + zone_name = "${azurerm_dns_zone.test.name}" + ttl = "300" + + record { + priority = 1 + weight = 5 + port = 8080 + target = "target1.contoso.com" + } + + record { + priority = 2 + weight = 25 + port = 8080 + target = "target2.contoso.com" + } +} +` + +var testAccAzureRMDnsSrvRecord_updateRecords = ` +resource "azurerm_resource_group" "test" { + name = "acctest_rg_%d" + location = "West US" +} +resource "azurerm_dns_zone" "test" { + name = "acctestzone%d.com" + resource_group_name = "${azurerm_resource_group.test.name}" +} + +resource "azurerm_dns_srv_record" "test" { + name = "myarecord%d" + resource_group_name = "${azurerm_resource_group.test.name}" + zone_name = "${azurerm_dns_zone.test.name}" + ttl = "300" + + record { + priority = 1 + weight = 5 + port = 8080 + target = "target1.contoso.com" + } + + record { + priority = 2 + weight = 25 + port = 8080 + target = "target2.contoso.com" + } + + record { + priority = 3 + weight = 100 + port = 8080 + target = "target3.contoso.com" + } +} +` + +var testAccAzureRMDnsSrvRecord_withTags = ` +resource "azurerm_resource_group" "test" { + name = "acctest_rg_%d" + location = "West US" +} +resource "azurerm_dns_zone" "test" { + name = "acctestzone%d.com" + resource_group_name = "${azurerm_resource_group.test.name}" +} + +resource "azurerm_dns_srv_record" "test" { + name = "myarecord%d" + resource_group_name = "${azurerm_resource_group.test.name}" + zone_name = "${azurerm_dns_zone.test.name}" + ttl = "300" + + record { + priority = 1 + weight = 5 + port = 8080 + target = "target1.contoso.com" + } + + record { + priority = 2 + weight = 25 + port = 8080 + target = "target2.contoso.com" + } + + tags { + environment = "Production" + cost_center = "MSFT" + } +} +` + +var testAccAzureRMDnsSrvRecord_withTagsUpdate = ` +resource "azurerm_resource_group" "test" { + name = "acctest_rg_%d" + location = "West US" +} +resource "azurerm_dns_zone" "test" { + name = "acctestzone%d.com" + resource_group_name = "${azurerm_resource_group.test.name}" +} + +resource "azurerm_dns_srv_record" "test" { + name = "myarecord%d" + resource_group_name = "${azurerm_resource_group.test.name}" + zone_name = "${azurerm_dns_zone.test.name}" + ttl = "300" + + record { + priority = 1 + weight = 5 + port = 8080 + target = "target1.contoso.com" + } + + record { + priority = 2 + weight = 25 + port = 8080 + target = "target2.contoso.com" + } + + tags { + environment = "staging" + } +} +` diff --git a/builtin/providers/azurerm/resource_arm_dns_txt_record.go b/builtin/providers/azurerm/resource_arm_dns_txt_record.go new file mode 100644 index 000000000..d4f71dba5 --- /dev/null +++ b/builtin/providers/azurerm/resource_arm_dns_txt_record.go @@ -0,0 +1,194 @@ +package azurerm + +import ( + "fmt" + "log" + + "github.com/hashicorp/terraform/helper/schema" + "github.com/jen20/riviera/dns" +) + +func resourceArmDnsTxtRecord() *schema.Resource { + return &schema.Resource{ + Create: resourceArmDnsTxtRecordCreate, + Read: resourceArmDnsTxtRecordRead, + Update: resourceArmDnsTxtRecordCreate, + Delete: resourceArmDnsTxtRecordDelete, + + Schema: map[string]*schema.Schema{ + "name": &schema.Schema{ + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + + "resource_group_name": &schema.Schema{ + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + + "zone_name": &schema.Schema{ + Type: schema.TypeString, + Required: true, + }, + + "record": &schema.Schema{ + Type: schema.TypeSet, + Required: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "value": &schema.Schema{ + Type: schema.TypeString, + Required: true, + }, + }, + }, + }, + + "ttl": &schema.Schema{ + Type: schema.TypeInt, + Required: true, + }, + + "tags": tagsSchema(), + }, + } +} + +func resourceArmDnsTxtRecordCreate(d *schema.ResourceData, meta interface{}) error { + client := meta.(*ArmClient) + rivieraClient := client.rivieraClient + + tags := d.Get("tags").(map[string]interface{}) + expandedTags := expandTags(tags) + + createCommand := &dns.CreateTXTRecordSet{ + Name: d.Get("name").(string), + Location: "global", + ResourceGroupName: d.Get("resource_group_name").(string), + ZoneName: d.Get("zone_name").(string), + TTL: d.Get("ttl").(int), + Tags: *expandedTags, + } + + txtRecords, recordErr := expandAzureRmDnsTxtRecords(d) + if recordErr != nil { + return fmt.Errorf("Error Building list of Azure RM Txt Records: %s", recordErr) + } + createCommand.TXTRecords = txtRecords + + createRequest := rivieraClient.NewRequest() + createRequest.Command = createCommand + + createResponse, err := createRequest.Execute() + if err != nil { + return fmt.Errorf("Error creating DNS TXT Record: %s", err) + } + if !createResponse.IsSuccessful() { + return fmt.Errorf("Error creating DNS TXT Record: %s", createResponse.Error) + } + + readRequest := rivieraClient.NewRequest() + readRequest.Command = &dns.GetTXTRecordSet{ + Name: d.Get("name").(string), + ResourceGroupName: d.Get("resource_group_name").(string), + ZoneName: d.Get("zone_name").(string), + } + + readResponse, err := readRequest.Execute() + if err != nil { + return fmt.Errorf("Error reading DNS TXT Record: %s", err) + } + if !readResponse.IsSuccessful() { + return fmt.Errorf("Error reading DNS TXT Record: %s", readResponse.Error) + } + + resp := readResponse.Parsed.(*dns.GetTXTRecordSetResponse) + d.SetId(resp.ID) + + return resourceArmDnsTxtRecordRead(d, meta) +} + +func resourceArmDnsTxtRecordRead(d *schema.ResourceData, meta interface{}) error { + client := meta.(*ArmClient) + rivieraClient := client.rivieraClient + + readRequest := rivieraClient.NewRequestForURI(d.Id()) + readRequest.Command = &dns.GetTXTRecordSet{} + + readResponse, err := readRequest.Execute() + if err != nil { + return fmt.Errorf("Error reading DNS TXT Record: %s", err) + } + if !readResponse.IsSuccessful() { + log.Printf("[INFO] Error reading DNS TXT Record %q - removing from state", d.Id()) + d.SetId("") + return fmt.Errorf("Error reading DNS TXT Record: %s", readResponse.Error) + } + + resp := readResponse.Parsed.(*dns.GetTXTRecordSetResponse) + + d.Set("ttl", resp.TTL) + + if resp.TXTRecords != nil { + if err := d.Set("record", flattenAzureRmDnsTxtRecords(resp.TXTRecords)); err != nil { + log.Printf("[INFO] Error setting the Azure RM TXT Record State: %s", err) + return err + } + } + + flattenAndSetTags(d, &resp.Tags) + + return nil +} + +func resourceArmDnsTxtRecordDelete(d *schema.ResourceData, meta interface{}) error { + client := meta.(*ArmClient) + rivieraClient := client.rivieraClient + + deleteRequest := rivieraClient.NewRequestForURI(d.Id()) + deleteRequest.Command = &dns.DeleteRecordSet{ + RecordSetType: "TXT", + } + + deleteResponse, err := deleteRequest.Execute() + if err != nil { + return fmt.Errorf("Error deleting DNS TXT Record: %s", err) + } + if !deleteResponse.IsSuccessful() { + return fmt.Errorf("Error deleting DNS TXT Record: %s", deleteResponse.Error) + } + + return nil +} + +func expandAzureRmDnsTxtRecords(d *schema.ResourceData) ([]dns.TXTRecord, error) { + configs := d.Get("record").(*schema.Set).List() + txtRecords := make([]dns.TXTRecord, 0, len(configs)) + + for _, configRaw := range configs { + data := configRaw.(map[string]interface{}) + + txtRecord := dns.TXTRecord{ + Value: data["value"].(string), + } + + txtRecords = append(txtRecords, txtRecord) + + } + + return txtRecords, nil + +} + +func flattenAzureRmDnsTxtRecords(records []dns.TXTRecord) []map[string]interface{} { + result := make([]map[string]interface{}, 0, len(records)) + for _, record := range records { + txtRecord := make(map[string]interface{}) + txtRecord["value"] = record.Value + + result = append(result, txtRecord) + } + return result +} diff --git a/builtin/providers/azurerm/resource_arm_dns_txt_record_test.go b/builtin/providers/azurerm/resource_arm_dns_txt_record_test.go new file mode 100644 index 000000000..3d08878e3 --- /dev/null +++ b/builtin/providers/azurerm/resource_arm_dns_txt_record_test.go @@ -0,0 +1,257 @@ +package azurerm + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform/helper/acctest" + "github.com/hashicorp/terraform/helper/resource" + "github.com/hashicorp/terraform/terraform" + "github.com/jen20/riviera/dns" +) + +func TestAccAzureRMDnsTxtRecord_basic(t *testing.T) { + ri := acctest.RandInt() + config := fmt.Sprintf(testAccAzureRMDnsTxtRecord_basic, ri, ri, ri) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMDnsTxtRecordDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: config, + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMDnsTxtRecordExists("azurerm_dns_txt_record.test"), + ), + }, + }, + }) +} + +func TestAccAzureRMDnsTxtRecord_updateRecords(t *testing.T) { + ri := acctest.RandInt() + preConfig := fmt.Sprintf(testAccAzureRMDnsTxtRecord_basic, ri, ri, ri) + postConfig := fmt.Sprintf(testAccAzureRMDnsTxtRecord_updateRecords, ri, ri, ri) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMDnsTxtRecordDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: preConfig, + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMDnsTxtRecordExists("azurerm_dns_txt_record.test"), + resource.TestCheckResourceAttr( + "azurerm_dns_txt_record.test", "record.#", "2"), + ), + }, + + resource.TestStep{ + Config: postConfig, + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMDnsTxtRecordExists("azurerm_dns_txt_record.test"), + resource.TestCheckResourceAttr( + "azurerm_dns_txt_record.test", "record.#", "3"), + ), + }, + }, + }) +} + +func TestAccAzureRMDnsTxtRecord_withTags(t *testing.T) { + ri := acctest.RandInt() + preConfig := fmt.Sprintf(testAccAzureRMDnsTxtRecord_withTags, ri, ri, ri) + postConfig := fmt.Sprintf(testAccAzureRMDnsTxtRecord_withTagsUpdate, ri, ri, ri) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMDnsTxtRecordDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: preConfig, + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMDnsTxtRecordExists("azurerm_dns_txt_record.test"), + resource.TestCheckResourceAttr( + "azurerm_dns_txt_record.test", "tags.#", "2"), + ), + }, + + resource.TestStep{ + Config: postConfig, + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMDnsTxtRecordExists("azurerm_dns_txt_record.test"), + resource.TestCheckResourceAttr( + "azurerm_dns_txt_record.test", "tags.#", "1"), + ), + }, + }, + }) +} + +func testCheckAzureRMDnsTxtRecordExists(name string) resource.TestCheckFunc { + return func(s *terraform.State) error { + // Ensure we have enough information in state to look up in API + rs, ok := s.RootModule().Resources[name] + if !ok { + return fmt.Errorf("Not found: %s", name) + } + + conn := testAccProvider.Meta().(*ArmClient).rivieraClient + + readRequest := conn.NewRequestForURI(rs.Primary.ID) + readRequest.Command = &dns.GetTXTRecordSet{} + + readResponse, err := readRequest.Execute() + if err != nil { + return fmt.Errorf("Bad: GetTXTRecordSet: %s", err) + } + if !readResponse.IsSuccessful() { + return fmt.Errorf("Bad: GetTXTRecordSet: %s", readResponse.Error) + } + + return nil + } +} + +func testCheckAzureRMDnsTxtRecordDestroy(s *terraform.State) error { + conn := testAccProvider.Meta().(*ArmClient).rivieraClient + + for _, rs := range s.RootModule().Resources { + if rs.Type != "azurerm_dns_txt_record" { + continue + } + + readRequest := conn.NewRequestForURI(rs.Primary.ID) + readRequest.Command = &dns.GetTXTRecordSet{} + + readResponse, err := readRequest.Execute() + if err != nil { + return fmt.Errorf("Bad: GetTXTRecordSet: %s", err) + } + + if readResponse.IsSuccessful() { + return fmt.Errorf("Bad: DNS TXT Record still exists: %s", readResponse.Error) + } + } + + return nil +} + +var testAccAzureRMDnsTxtRecord_basic = ` +resource "azurerm_resource_group" "test" { + name = "acctest_rg_%d" + location = "West US" +} +resource "azurerm_dns_zone" "test" { + name = "acctestzone%d.com" + resource_group_name = "${azurerm_resource_group.test.name}" +} + +resource "azurerm_dns_txt_record" "test" { + name = "myarecord%d" + resource_group_name = "${azurerm_resource_group.test.name}" + zone_name = "${azurerm_dns_zone.test.name}" + ttl = "300" + + record { + value = "Quick brown fox" + } + + record { + value = "Another test txt string" + } +} +` + +var testAccAzureRMDnsTxtRecord_updateRecords = ` +resource "azurerm_resource_group" "test" { + name = "acctest_rg_%d" + location = "West US" +} +resource "azurerm_dns_zone" "test" { + name = "acctestzone%d.com" + resource_group_name = "${azurerm_resource_group.test.name}" +} + +resource "azurerm_dns_txt_record" "test" { + name = "myarecord%d" + resource_group_name = "${azurerm_resource_group.test.name}" + zone_name = "${azurerm_dns_zone.test.name}" + ttl = "300" + + record { + value = "Quick brown fox" + } + + record { + value = "Another test txt string" + } + + record { + value = "A wild 3rd record appears" + } +} +` + +var testAccAzureRMDnsTxtRecord_withTags = ` +resource "azurerm_resource_group" "test" { + name = "acctest_rg_%d" + location = "West US" +} +resource "azurerm_dns_zone" "test" { + name = "acctestzone%d.com" + resource_group_name = "${azurerm_resource_group.test.name}" +} + +resource "azurerm_dns_txt_record" "test" { + name = "myarecord%d" + resource_group_name = "${azurerm_resource_group.test.name}" + zone_name = "${azurerm_dns_zone.test.name}" + ttl = "300" + + record { + value = "Quick brown fox" + } + + record { + value = "Another test txt string" + } + + tags { + environment = "Production" + cost_center = "MSFT" + } +} +` + +var testAccAzureRMDnsTxtRecord_withTagsUpdate = ` +resource "azurerm_resource_group" "test" { + name = "acctest_rg_%d" + location = "West US" +} +resource "azurerm_dns_zone" "test" { + name = "acctestzone%d.com" + resource_group_name = "${azurerm_resource_group.test.name}" +} + +resource "azurerm_dns_txt_record" "test" { + name = "myarecord%d" + resource_group_name = "${azurerm_resource_group.test.name}" + zone_name = "${azurerm_dns_zone.test.name}" + ttl = "300" + record { + value = "Quick brown fox" + } + + record { + value = "Another test txt string" + } + + tags { + environment = "staging" + } +} +` diff --git a/vendor/github.com/jen20/riviera/dns/create_dns_txt_recordset.go b/vendor/github.com/jen20/riviera/dns/create_dns_txt_recordset.go index 66ce95a42..efe9429e9 100644 --- a/vendor/github.com/jen20/riviera/dns/create_dns_txt_recordset.go +++ b/vendor/github.com/jen20/riviera/dns/create_dns_txt_recordset.go @@ -3,7 +3,7 @@ package dns import "github.com/jen20/riviera/azure" type TXTRecord struct { - Value int `json:"value" mapstructure:"value"` + Value string `json:"value" mapstructure:"value"` } type CreateTXTRecordSetResponse struct { diff --git a/vendor/github.com/jen20/riviera/dns/get_dns_soa_recordset.go b/vendor/github.com/jen20/riviera/dns/get_dns_soa_recordset.go index 51c78d9fa..0d8a71f4d 100644 --- a/vendor/github.com/jen20/riviera/dns/get_dns_soa_recordset.go +++ b/vendor/github.com/jen20/riviera/dns/get_dns_soa_recordset.go @@ -3,12 +3,12 @@ package dns import "github.com/jen20/riviera/azure" type GetSOARecordSetResponse struct { - ID string `mapstructure:"id"` - Name string `mapstructure:"name"` - Location string `mapstructure:"location"` - Tags map[string]*string `mapstructure:"tags"` - TTL *int `mapstructure:"TTL"` - SOARecords []SOARecord `mapstructure:"SOARecords"` + ID string `mapstructure:"id"` + Name string `mapstructure:"name"` + Location string `mapstructure:"location"` + Tags map[string]*string `mapstructure:"tags"` + TTL *int `mapstructure:"TTL"` + SOARecord SOARecord `mapstructure:"SOARecord"` } type GetSOARecordSet struct { diff --git a/vendor/github.com/jen20/riviera/dns/get_dns_txt_recordset.go b/vendor/github.com/jen20/riviera/dns/get_dns_txt_recordset.go new file mode 100644 index 000000000..7e707a3eb --- /dev/null +++ b/vendor/github.com/jen20/riviera/dns/get_dns_txt_recordset.go @@ -0,0 +1,29 @@ +package dns + +import "github.com/jen20/riviera/azure" + +type GetTXTRecordSetResponse struct { + ID string `mapstructure:"id"` + Name string `mapstructure:"name"` + Location string `mapstructure:"location"` + Tags map[string]*string `mapstructure:"tags"` + TTL *int `mapstructure:"TTL"` + TXTRecords []TXTRecord `mapstructure:"TXTRecords"` +} + +type GetTXTRecordSet struct { + Name string `json:"-"` + ResourceGroupName string `json:"-"` + ZoneName string `json:"-"` +} + +func (command GetTXTRecordSet) APIInfo() azure.APIInfo { + return azure.APIInfo{ + APIVersion: apiVersion, + Method: "GET", + URLPathFunc: dnsRecordSetDefaultURLPathFunc(command.ResourceGroupName, command.ZoneName, "TXT", command.Name), + ResponseTypeFunc: func() interface{} { + return &GetTXTRecordSetResponse{} + }, + } +} diff --git a/vendor/github.com/jen20/riviera/dns/create_dns_soa_recordset.go b/vendor/github.com/jen20/riviera/dns/update_dns_soa_recordset.go similarity index 63% rename from vendor/github.com/jen20/riviera/dns/create_dns_soa_recordset.go rename to vendor/github.com/jen20/riviera/dns/update_dns_soa_recordset.go index 50b587861..d4518c249 100644 --- a/vendor/github.com/jen20/riviera/dns/create_dns_soa_recordset.go +++ b/vendor/github.com/jen20/riviera/dns/update_dns_soa_recordset.go @@ -11,32 +11,32 @@ type SOARecord struct { RetryTime int `json:"retryTime" mapstructure:"retryTime"` } -type CreateSOARecordSetResponse struct { - ID string `mapstructure:"id"` - Name string `mapstructure:"name"` - Location string `mapstructure:"location"` - Tags map[string]*string `mapstructure:"tags"` - TTL *int `mapstructure:"TTL"` - SOARecords []SOARecord `mapstructure:"SOARecords"` +type UpdateSOARecordSetResponse struct { + ID string `mapstructure:"id"` + Name string `mapstructure:"name"` + Location string `mapstructure:"location"` + Tags map[string]*string `mapstructure:"tags"` + TTL *int `mapstructure:"TTL"` + SOARecord SOARecord `mapstructure:"SOARecord"` } -type CreateSOARecordSet struct { +type UpdateSOARecordSet struct { Name string `json:"-"` ResourceGroupName string `json:"-"` ZoneName string `json:"-"` Location string `json:"-" riviera:"location"` Tags map[string]*string `json:"-" riviera:"tags"` TTL int `json:"TTL"` - SOARecords []SOARecord `json:"SOARecords"` + SOARecord SOARecord `json:"SOARecord"` } -func (command CreateSOARecordSet) APIInfo() azure.APIInfo { +func (command UpdateSOARecordSet) APIInfo() azure.APIInfo { return azure.APIInfo{ APIVersion: apiVersion, - Method: "PUT", + Method: "PATCH", URLPathFunc: dnsRecordSetDefaultURLPathFunc(command.ResourceGroupName, command.ZoneName, "SOA", command.Name), ResponseTypeFunc: func() interface{} { - return &CreateSOARecordSetResponse{} + return &UpdateSOARecordSetResponse{} }, } } diff --git a/website/source/docs/providers/azurerm/r/dns_mx_record.html.markdown b/website/source/docs/providers/azurerm/r/dns_mx_record.html.markdown new file mode 100644 index 000000000..961979162 --- /dev/null +++ b/website/source/docs/providers/azurerm/r/dns_mx_record.html.markdown @@ -0,0 +1,72 @@ +--- +layout: "azurerm" +page_title: "Azure Resource Manager: azurerm_dns_mx_record" +sidebar_current: "docs-azurerm-resource-dns-mx-record" +description: |- + Manage a DNS MX Record. +--- + +# azurerm\_dns\_mx\_record + +Enables you to manage DNS MX Records within Azure DNS. + +## Example Usage + +``` +resource "azurerm_resource_group" "test" { + name = "acceptanceTestResourceGroup1" + location = "West US" +} +resource "azurerm_dns_zone" "test" { + name = "mydomain.com" + resource_group_name = "${azurerm_resource_group.test.name}" +} + +resource "azurerm_dns_mx_record" "test" { + name = "test" + zone_name = "${azurerm_dns_zone.test.name}" + resource_group_name = "${azurerm_resource_group.test.name}" + ttl = "300" + + record { + preference = 10 + exchange = "mail1.contoso.com" + } + + record { + preference = 20 + exchange = "mail2.contoso.com" + } + + tags { + Environment = "Production" + } +} +``` +## Argument Reference + +The following arguments are supported: + +* `name` - (Required) The name of the DNS MX Record. + +* `resource_group_name` - (Required) Specifies the resource group where the resource exists. Changing this forces a new resource to be created. + +* `zone_name` - (Required) Specifies the DNS Zone where the resource exists. Changing this forces a new resource to be created. + +* `TTL` - (Required) The Time To Live (TTL) of the DNS record. + +* `record` - (Required) A list of values that make up the SRV record. Each `record` block supports fields documented below. + +* `tags` - (Optional) A mapping of tags to assign to the resource. + +The `record` block supports: + +* `preference` - (Required) String representing the “preference” value of the MX records. Records with lower preference value take priority. + +* `exchange` - (Required) The mail server responsible for the domain covered by the MX record. + +## Attributes Reference + +The following attributes are exported: + +* `id` - The DNS MX Record ID. diff --git a/website/source/docs/providers/azurerm/r/dns_ns_record.html.markdown b/website/source/docs/providers/azurerm/r/dns_ns_record.html.markdown new file mode 100644 index 000000000..e160a1199 --- /dev/null +++ b/website/source/docs/providers/azurerm/r/dns_ns_record.html.markdown @@ -0,0 +1,67 @@ +--- +layout: "azurerm" +page_title: "Azure Resource Manager: azurerm_dns_ns_record" +sidebar_current: "docs-azurerm-resource-dns-ns-record" +description: |- + Create a DNS NS Record. +--- + +# azurerm\_dns\_ns\_record + +Enables you to manage DNS NS Records within Azure DNS. + +## Example Usage + +``` +resource "azurerm_resource_group" "test" { + name = "acceptanceTestResourceGroup1" + location = "West US" +} +resource "azurerm_dns_zone" "test" { + name = "mydomain.com" + resource_group_name = "${azurerm_resource_group.test.name}" +} + +resource "azurerm_dns_ns_record" "test" { + name = "test" + zone_name = "${azurerm_dns_zone.test.name}" + resource_group_name = "${azurerm_resource_group.test.name}" + ttl = "300" + record { + nsdname = "ns1.contoso.com" + } + + record { + nsdname = "ns2.contoso.com" + } + + tags { + Environment = "Production" + } +} +``` +## Argument Reference + +The following arguments are supported: + +* `name` - (Required) The name of the DNS NS Record. + +* `resource_group_name` - (Required) Specifies the resource group where the resource exists. Changing this forces a new resource to be created. + +* `zone_name` - (Required) Specifies the DNS Zone where the resource exists. Changing this forces a new resource to be created. + +* `TTL` - (Required) The Time To Live (TTL) of the DNS record. + +* `record` - (Required) A list of values that make up the NS record. Each `record` block supports fields documented below. + +* `tags` - (Optional) A mapping of tags to assign to the resource. + +The `record` block supports: + +* `nsdname` - (Required) The value of the record. + +## Attributes Reference + +The following attributes are exported: + +* `id` - The DNS NS Record ID. diff --git a/website/source/docs/providers/azurerm/r/dns_srv_record.html.markdown b/website/source/docs/providers/azurerm/r/dns_srv_record.html.markdown new file mode 100644 index 000000000..2a783a714 --- /dev/null +++ b/website/source/docs/providers/azurerm/r/dns_srv_record.html.markdown @@ -0,0 +1,74 @@ +--- +layout: "azurerm" +page_title: "Azure Resource Manager: azurerm_dns_srv_record" +sidebar_current: "docs-azurerm-resource-dns-srv-record" +description: |- + Manage a DNS SRV Record. +--- + +# azurerm\_dns\_srv\_record + +Enables you to manage DNS SRV Records within Azure DNS. + +## Example Usage + +``` +resource "azurerm_resource_group" "test" { + name = "acceptanceTestResourceGroup1" + location = "West US" +} +resource "azurerm_dns_zone" "test" { + name = "mydomain.com" + resource_group_name = "${azurerm_resource_group.test.name}" +} + +resource "azurerm_dns_srv_record" "test" { + name = "test" + zone_name = "${azurerm_dns_zone.test.name}" + resource_group_name = "${azurerm_resource_group.test.name}" + ttl = "300" + + record { + priority = 1 + weight = 5 + port = 8080 + target = "target1.contoso.com" + } + + tags { + Environment = "Production" + } +} +``` +## Argument Reference + +The following arguments are supported: + +* `name` - (Required) The name of the DNS SRV Record. + +* `resource_group_name` - (Required) Specifies the resource group where the resource exists. Changing this forces a new resource to be created. + +* `zone_name` - (Required) Specifies the DNS Zone where the resource exists. Changing this forces a new resource to be created. + +* `TTL` - (Required) The Time To Live (TTL) of the DNS record. + +* `record` - (Required) A list of values that make up the SRV record. Each `record` block supports fields documented below. + +* `tags` - (Optional) A mapping of tags to assign to the resource. + +The `record` block supports: + +* `priority` - (Required) Priority of the SRV record. + +* `weight` - (Required) Weight of the SRV record. + +* `port` - (Required) Port the service is listening on. + +* `target` - (Required) FQDN of the service. + + +## Attributes Reference + +The following attributes are exported: + +* `id` - The DNS SRV Record ID. diff --git a/website/source/docs/providers/azurerm/r/dns_txt_record.html.markdown b/website/source/docs/providers/azurerm/r/dns_txt_record.html.markdown new file mode 100644 index 000000000..df8e55f7c --- /dev/null +++ b/website/source/docs/providers/azurerm/r/dns_txt_record.html.markdown @@ -0,0 +1,66 @@ +--- +layout: "azurerm" +page_title: "Azure Resource Manager: azurerm_dns_txt_record" +sidebar_current: "docs-azurerm-resource-dns-txt-record" +description: |- + Create a DNS TXT Record. +--- + +# azurerm\_dns\_txt\_record + +Enables you to manage DNS TXT Records within Azure DNS. + +## Example Usage + +``` +resource "azurerm_resource_group" "test" { + name = "acceptanceTestResourceGroup1" + location = "West US" +} +resource "azurerm_dns_zone" "test" { + name = "mydomain.com" + resource_group_name = "${azurerm_resource_group.test.name}" +} + +resource "azurerm_dns_txt_record" "test" { + name = "test" + zone_name = "${azurerm_dns_zone.test.name}" + resource_group_name = "${azurerm_resource_group.test.name}" + ttl = "300" + record { + value = "google-site-authenticator" + } + record { + value = "more site information here" + } + + tags { + Environment = "Production" + } +} +``` +## Argument Reference + +The following arguments are supported: + +* `name` - (Required) The name of the DNS TXT Record. + +* `resource_group_name` - (Required) Specifies the resource group where the resource exists. Changing this forces a new resource to be created. + +* `zone_name` - (Required) Specifies the DNS Zone where the resource exists. Changing this forces a new resource to be created. + +* `TTL` - (Required) The Time To Live (TTL) of the DNS record. + +* `record` - (Required) A list of values that make up the txt record. Each `record` block supports fields documented below. + +* `tags` - (Optional) A mapping of tags to assign to the resource. + +The `record` block supports: + +* `value` - (Required) The value of the record. + +## Attributes Reference + +The following attributes are exported: + +* `id` - The DNS TXT Record ID. diff --git a/website/source/layouts/azurerm.erb b/website/source/layouts/azurerm.erb index 8ee9a8737..5d4fc9121 100644 --- a/website/source/layouts/azurerm.erb +++ b/website/source/layouts/azurerm.erb @@ -46,6 +46,22 @@ azurerm_dns_cname_record + > + azurerm_dns_mx_record + + + > + azurerm_dns_ns_record + + + > + azurerm_dns_srv_record + + + > + azurerm_dns_txt_record + + > azurerm_dns_zone