provider/openstack: Add DNS V2 RecordSet resource (#14813)
* vendor gophercloud dns v2 recordset deps * openstack dns v2 recordset resource * fix type assertion panic condition * address pr review feedback
This commit is contained in:
parent
acedf7228f
commit
e1c8d760d3
|
@ -0,0 +1,28 @@
|
|||
package openstack
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/terraform/helper/resource"
|
||||
)
|
||||
|
||||
func TestAccDNSV2RecordSet_importBasic(t *testing.T) {
|
||||
zoneName := randomZoneName()
|
||||
resourceName := "openstack_dns_recordset_v2.recordset_1"
|
||||
|
||||
resource.Test(t, resource.TestCase{
|
||||
PreCheck: func() { testAccPreCheckDNSRecordSetV2(t) },
|
||||
Providers: testAccProviders,
|
||||
CheckDestroy: testAccCheckDNSV2RecordSetDestroy,
|
||||
Steps: []resource.TestStep{
|
||||
resource.TestStep{
|
||||
Config: testAccDNSV2RecordSet_basic(zoneName),
|
||||
},
|
||||
resource.TestStep{
|
||||
ResourceName: resourceName,
|
||||
ImportState: true,
|
||||
ImportStateVerify: true,
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
|
@ -150,6 +150,7 @@ func Provider() terraform.ResourceProvider {
|
|||
"openstack_compute_floatingip_v2": resourceComputeFloatingIPV2(),
|
||||
"openstack_compute_floatingip_associate_v2": resourceComputeFloatingIPAssociateV2(),
|
||||
"openstack_compute_volume_attach_v2": resourceComputeVolumeAttachV2(),
|
||||
"openstack_dns_recordset_v2": resourceDNSRecordSetV2(),
|
||||
"openstack_dns_zone_v2": resourceDNSZoneV2(),
|
||||
"openstack_fw_firewall_v1": resourceFWFirewallV1(),
|
||||
"openstack_fw_policy_v1": resourceFWPolicyV1(),
|
||||
|
|
|
@ -0,0 +1,276 @@
|
|||
package openstack
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/gophercloud/gophercloud"
|
||||
"github.com/gophercloud/gophercloud/openstack/dns/v2/recordsets"
|
||||
|
||||
"github.com/hashicorp/terraform/helper/resource"
|
||||
"github.com/hashicorp/terraform/helper/schema"
|
||||
)
|
||||
|
||||
func resourceDNSRecordSetV2() *schema.Resource {
|
||||
return &schema.Resource{
|
||||
Create: resourceDNSRecordSetV2Create,
|
||||
Read: resourceDNSRecordSetV2Read,
|
||||
Update: resourceDNSRecordSetV2Update,
|
||||
Delete: resourceDNSRecordSetV2Delete,
|
||||
Importer: &schema.ResourceImporter{
|
||||
State: schema.ImportStatePassthrough,
|
||||
},
|
||||
|
||||
Timeouts: &schema.ResourceTimeout{
|
||||
Create: schema.DefaultTimeout(10 * time.Minute),
|
||||
Update: schema.DefaultTimeout(10 * time.Minute),
|
||||
Delete: schema.DefaultTimeout(10 * time.Minute),
|
||||
},
|
||||
|
||||
Schema: map[string]*schema.Schema{
|
||||
"region": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
ForceNew: true,
|
||||
DefaultFunc: schema.EnvDefaultFunc("OS_REGION_NAME", ""),
|
||||
},
|
||||
"zone_id": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
ForceNew: true,
|
||||
},
|
||||
"name": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
ForceNew: true,
|
||||
},
|
||||
"description": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
ForceNew: false,
|
||||
},
|
||||
"records": &schema.Schema{
|
||||
Type: schema.TypeList,
|
||||
Optional: true,
|
||||
ForceNew: false,
|
||||
Elem: &schema.Schema{Type: schema.TypeString},
|
||||
},
|
||||
"ttl": &schema.Schema{
|
||||
Type: schema.TypeInt,
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
ForceNew: false,
|
||||
},
|
||||
"type": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
ForceNew: true,
|
||||
},
|
||||
"value_specs": &schema.Schema{
|
||||
Type: schema.TypeMap,
|
||||
Optional: true,
|
||||
ForceNew: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func resourceDNSRecordSetV2Create(d *schema.ResourceData, meta interface{}) error {
|
||||
config := meta.(*Config)
|
||||
dnsClient, err := config.dnsV2Client(GetRegion(d))
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error creating OpenStack DNS client: %s", err)
|
||||
}
|
||||
|
||||
recordsraw := d.Get("records").([]interface{})
|
||||
records := make([]string, len(recordsraw))
|
||||
for i, recordraw := range recordsraw {
|
||||
records[i] = recordraw.(string)
|
||||
}
|
||||
|
||||
createOpts := RecordSetCreateOpts{
|
||||
recordsets.CreateOpts{
|
||||
Name: d.Get("name").(string),
|
||||
Description: d.Get("description").(string),
|
||||
Records: records,
|
||||
TTL: d.Get("ttl").(int),
|
||||
Type: d.Get("type").(string),
|
||||
},
|
||||
MapValueSpecs(d),
|
||||
}
|
||||
|
||||
zoneID := d.Get("zone_id").(string)
|
||||
|
||||
log.Printf("[DEBUG] Create Options: %#v", createOpts)
|
||||
n, err := recordsets.Create(dnsClient, zoneID, createOpts).Extract()
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error creating OpenStack DNS record set: %s", err)
|
||||
}
|
||||
|
||||
log.Printf("[DEBUG] Waiting for DNS record set (%s) to become available", n.ID)
|
||||
stateConf := &resource.StateChangeConf{
|
||||
Target: []string{"ACTIVE"},
|
||||
Pending: []string{"PENDING"},
|
||||
Refresh: waitForDNSRecordSet(dnsClient, zoneID, n.ID),
|
||||
Timeout: d.Timeout(schema.TimeoutCreate),
|
||||
Delay: 5 * time.Second,
|
||||
MinTimeout: 3 * time.Second,
|
||||
}
|
||||
|
||||
_, err = stateConf.WaitForState()
|
||||
|
||||
id := fmt.Sprintf("%s/%s", zoneID, n.ID)
|
||||
d.SetId(id)
|
||||
|
||||
log.Printf("[DEBUG] Created OpenStack DNS record set %s: %#v", n.ID, n)
|
||||
return resourceDNSRecordSetV2Read(d, meta)
|
||||
}
|
||||
|
||||
func resourceDNSRecordSetV2Read(d *schema.ResourceData, meta interface{}) error {
|
||||
config := meta.(*Config)
|
||||
dnsClient, err := config.dnsV2Client(GetRegion(d))
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error creating OpenStack DNS client: %s", err)
|
||||
}
|
||||
|
||||
// Obtain relevant info from parsing the ID
|
||||
zoneID, recordsetID, err := parseDNSV2RecordSetID(d.Id())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
n, err := recordsets.Get(dnsClient, zoneID, recordsetID).Extract()
|
||||
if err != nil {
|
||||
return CheckDeleted(d, err, "record_set")
|
||||
}
|
||||
|
||||
log.Printf("[DEBUG] Retrieved record set %s: %#v", recordsetID, n)
|
||||
|
||||
d.Set("name", n.Name)
|
||||
d.Set("description", n.Description)
|
||||
d.Set("ttl", n.TTL)
|
||||
d.Set("type", n.Type)
|
||||
d.Set("records", n.Records)
|
||||
d.Set("region", GetRegion(d))
|
||||
d.Set("zone_id", zoneID)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func resourceDNSRecordSetV2Update(d *schema.ResourceData, meta interface{}) error {
|
||||
config := meta.(*Config)
|
||||
dnsClient, err := config.dnsV2Client(GetRegion(d))
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error creating OpenStack DNS client: %s", err)
|
||||
}
|
||||
|
||||
var updateOpts recordsets.UpdateOpts
|
||||
if d.HasChange("ttl") {
|
||||
updateOpts.TTL = d.Get("ttl").(int)
|
||||
}
|
||||
|
||||
if d.HasChange("records") {
|
||||
recordsraw := d.Get("records").([]interface{})
|
||||
records := make([]string, len(recordsraw))
|
||||
for i, recordraw := range recordsraw {
|
||||
records[i] = recordraw.(string)
|
||||
}
|
||||
updateOpts.Records = records
|
||||
}
|
||||
|
||||
if d.HasChange("description") {
|
||||
updateOpts.Description = d.Get("description").(string)
|
||||
}
|
||||
|
||||
// Obtain relevant info from parsing the ID
|
||||
zoneID, recordsetID, err := parseDNSV2RecordSetID(d.Id())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Printf("[DEBUG] Updating record set %s with options: %#v", recordsetID, updateOpts)
|
||||
|
||||
_, err = recordsets.Update(dnsClient, zoneID, recordsetID, updateOpts).Extract()
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error updating OpenStack DNS record set: %s", err)
|
||||
}
|
||||
|
||||
log.Printf("[DEBUG] Waiting for DNS record set (%s) to update", recordsetID)
|
||||
stateConf := &resource.StateChangeConf{
|
||||
Target: []string{"ACTIVE"},
|
||||
Pending: []string{"PENDING"},
|
||||
Refresh: waitForDNSRecordSet(dnsClient, zoneID, recordsetID),
|
||||
Timeout: d.Timeout(schema.TimeoutUpdate),
|
||||
Delay: 5 * time.Second,
|
||||
MinTimeout: 3 * time.Second,
|
||||
}
|
||||
|
||||
_, err = stateConf.WaitForState()
|
||||
|
||||
return resourceDNSRecordSetV2Read(d, meta)
|
||||
}
|
||||
|
||||
func resourceDNSRecordSetV2Delete(d *schema.ResourceData, meta interface{}) error {
|
||||
config := meta.(*Config)
|
||||
dnsClient, err := config.dnsV2Client(GetRegion(d))
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error creating OpenStack DNS client: %s", err)
|
||||
}
|
||||
|
||||
// Obtain relevant info from parsing the ID
|
||||
zoneID, recordsetID, err := parseDNSV2RecordSetID(d.Id())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = recordsets.Delete(dnsClient, zoneID, recordsetID).ExtractErr()
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error deleting OpenStack DNS record set: %s", err)
|
||||
}
|
||||
|
||||
log.Printf("[DEBUG] Waiting for DNS record set (%s) to be deleted", recordsetID)
|
||||
stateConf := &resource.StateChangeConf{
|
||||
Target: []string{"DELETED"},
|
||||
Pending: []string{"ACTIVE", "PENDING"},
|
||||
Refresh: waitForDNSRecordSet(dnsClient, zoneID, recordsetID),
|
||||
Timeout: d.Timeout(schema.TimeoutDelete),
|
||||
Delay: 5 * time.Second,
|
||||
MinTimeout: 3 * time.Second,
|
||||
}
|
||||
|
||||
_, err = stateConf.WaitForState()
|
||||
|
||||
d.SetId("")
|
||||
return nil
|
||||
}
|
||||
|
||||
func waitForDNSRecordSet(dnsClient *gophercloud.ServiceClient, zoneID, recordsetId string) resource.StateRefreshFunc {
|
||||
return func() (interface{}, string, error) {
|
||||
recordset, err := recordsets.Get(dnsClient, zoneID, recordsetId).Extract()
|
||||
if err != nil {
|
||||
if _, ok := err.(gophercloud.ErrDefault404); ok {
|
||||
return recordset, "DELETED", nil
|
||||
}
|
||||
|
||||
return nil, "", err
|
||||
}
|
||||
|
||||
log.Printf("[DEBUG] OpenStack DNS record set (%s) current status: %s", recordset.ID, recordset.Status)
|
||||
return recordset, recordset.Status, nil
|
||||
}
|
||||
}
|
||||
|
||||
func parseDNSV2RecordSetID(id string) (string, string, error) {
|
||||
idParts := strings.Split(id, "/")
|
||||
if len(idParts) != 2 {
|
||||
return "", "", fmt.Errorf("Unable to determine DNS record set ID from raw ID: %s", id)
|
||||
}
|
||||
|
||||
zoneID := idParts[0]
|
||||
recordsetID := idParts[1]
|
||||
|
||||
return zoneID, recordsetID, nil
|
||||
}
|
|
@ -0,0 +1,249 @@
|
|||
package openstack
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"regexp"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/terraform/helper/acctest"
|
||||
"github.com/hashicorp/terraform/helper/resource"
|
||||
"github.com/hashicorp/terraform/terraform"
|
||||
|
||||
"github.com/gophercloud/gophercloud/openstack/dns/v2/recordsets"
|
||||
)
|
||||
|
||||
func randomZoneName() string {
|
||||
return fmt.Sprintf("ACPTTEST-zone-%s.com.", acctest.RandString(5))
|
||||
}
|
||||
|
||||
func TestAccDNSV2RecordSet_basic(t *testing.T) {
|
||||
var recordset recordsets.RecordSet
|
||||
zoneName := randomZoneName()
|
||||
|
||||
resource.Test(t, resource.TestCase{
|
||||
PreCheck: func() { testAccPreCheckDNSRecordSetV2(t) },
|
||||
Providers: testAccProviders,
|
||||
CheckDestroy: testAccCheckDNSV2RecordSetDestroy,
|
||||
Steps: []resource.TestStep{
|
||||
resource.TestStep{
|
||||
Config: testAccDNSV2RecordSet_basic(zoneName),
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
testAccCheckDNSV2RecordSetExists("openstack_dns_recordset_v2.recordset_1", &recordset),
|
||||
resource.TestCheckResourceAttr(
|
||||
"openstack_dns_recordset_v2.recordset_1", "description", "a record set"),
|
||||
resource.TestCheckResourceAttr(
|
||||
"openstack_dns_recordset_v2.recordset_1", "records.0", "10.1.0.0"),
|
||||
),
|
||||
},
|
||||
resource.TestStep{
|
||||
Config: testAccDNSV2RecordSet_update(zoneName),
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
resource.TestCheckResourceAttr("openstack_dns_recordset_v2.recordset_1", "name", zoneName),
|
||||
resource.TestCheckResourceAttr("openstack_dns_recordset_v2.recordset_1", "ttl", "6000"),
|
||||
resource.TestCheckResourceAttr("openstack_dns_recordset_v2.recordset_1", "type", "A"),
|
||||
resource.TestCheckResourceAttr(
|
||||
"openstack_dns_recordset_v2.recordset_1", "description", "an updated record set"),
|
||||
resource.TestCheckResourceAttr(
|
||||
"openstack_dns_recordset_v2.recordset_1", "records.0", "10.1.0.1"),
|
||||
),
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func TestAccDNSV2RecordSet_readTTL(t *testing.T) {
|
||||
var recordset recordsets.RecordSet
|
||||
zoneName := randomZoneName()
|
||||
|
||||
resource.Test(t, resource.TestCase{
|
||||
PreCheck: func() { testAccPreCheckDNSRecordSetV2(t) },
|
||||
Providers: testAccProviders,
|
||||
CheckDestroy: testAccCheckDNSV2RecordSetDestroy,
|
||||
Steps: []resource.TestStep{
|
||||
resource.TestStep{
|
||||
Config: testAccDNSV2RecordSet_readTTL(zoneName),
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
testAccCheckDNSV2RecordSetExists("openstack_dns_recordset_v2.recordset_1", &recordset),
|
||||
resource.TestMatchResourceAttr(
|
||||
"openstack_dns_recordset_v2.recordset_1", "ttl", regexp.MustCompile("^[0-9]+$")),
|
||||
),
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func TestAccDNSV2RecordSet_timeout(t *testing.T) {
|
||||
var recordset recordsets.RecordSet
|
||||
zoneName := randomZoneName()
|
||||
|
||||
resource.Test(t, resource.TestCase{
|
||||
PreCheck: func() { testAccPreCheckDNSRecordSetV2(t) },
|
||||
Providers: testAccProviders,
|
||||
CheckDestroy: testAccCheckDNSV2RecordSetDestroy,
|
||||
Steps: []resource.TestStep{
|
||||
resource.TestStep{
|
||||
Config: testAccDNSV2RecordSet_timeout(zoneName),
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
testAccCheckDNSV2RecordSetExists("openstack_dns_recordset_v2.recordset_1", &recordset),
|
||||
),
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func testAccCheckDNSV2RecordSetDestroy(s *terraform.State) error {
|
||||
config := testAccProvider.Meta().(*Config)
|
||||
dnsClient, err := config.dnsV2Client(OS_REGION_NAME)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error creating OpenStack DNS client: %s", err)
|
||||
}
|
||||
|
||||
for _, rs := range s.RootModule().Resources {
|
||||
if rs.Type != "openstack_dns_recordset_v2" {
|
||||
continue
|
||||
}
|
||||
|
||||
zoneID, recordsetID, err := parseDNSV2RecordSetID(rs.Primary.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = recordsets.Get(dnsClient, zoneID, recordsetID).Extract()
|
||||
if err == nil {
|
||||
return fmt.Errorf("Record set still exists")
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func testAccCheckDNSV2RecordSetExists(n string, recordset *recordsets.RecordSet) resource.TestCheckFunc {
|
||||
return func(s *terraform.State) error {
|
||||
rs, ok := s.RootModule().Resources[n]
|
||||
if !ok {
|
||||
return fmt.Errorf("Not found: %s", n)
|
||||
}
|
||||
|
||||
if rs.Primary.ID == "" {
|
||||
return fmt.Errorf("No ID is set")
|
||||
}
|
||||
|
||||
config := testAccProvider.Meta().(*Config)
|
||||
dnsClient, err := config.dnsV2Client(OS_REGION_NAME)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error creating OpenStack DNS client: %s", err)
|
||||
}
|
||||
|
||||
zoneID, recordsetID, err := parseDNSV2RecordSetID(rs.Primary.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
found, err := recordsets.Get(dnsClient, zoneID, recordsetID).Extract()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if found.ID != recordsetID {
|
||||
return fmt.Errorf("Record set not found")
|
||||
}
|
||||
|
||||
*recordset = *found
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func testAccPreCheckDNSRecordSetV2(t *testing.T) {
|
||||
if os.Getenv("OS_AUTH_URL") == "" {
|
||||
t.Fatal("OS_AUTH_URL must be set for acceptance tests")
|
||||
}
|
||||
}
|
||||
|
||||
func testAccDNSV2RecordSet_basic(zoneName string) string {
|
||||
return fmt.Sprintf(`
|
||||
resource "openstack_dns_zone_v2" "zone_1" {
|
||||
name = "%s"
|
||||
email = "email2@example.com"
|
||||
description = "a zone"
|
||||
ttl = 6000
|
||||
type = "PRIMARY"
|
||||
}
|
||||
|
||||
resource "openstack_dns_recordset_v2" "recordset_1" {
|
||||
zone_id = "${openstack_dns_zone_v2.zone_1.id}"
|
||||
name = "%s"
|
||||
type = "A"
|
||||
description = "a record set"
|
||||
ttl = 3000
|
||||
records = ["10.1.0.0"]
|
||||
}
|
||||
`, zoneName, zoneName)
|
||||
}
|
||||
|
||||
func testAccDNSV2RecordSet_update(zoneName string) string {
|
||||
return fmt.Sprintf(`
|
||||
resource "openstack_dns_zone_v2" "zone_1" {
|
||||
name = "%s"
|
||||
email = "email2@example.com"
|
||||
description = "an updated zone"
|
||||
ttl = 6000
|
||||
type = "PRIMARY"
|
||||
}
|
||||
|
||||
resource "openstack_dns_recordset_v2" "recordset_1" {
|
||||
zone_id = "${openstack_dns_zone_v2.zone_1.id}"
|
||||
name = "%s"
|
||||
type = "A"
|
||||
description = "an updated record set"
|
||||
ttl = 6000
|
||||
records = ["10.1.0.1"]
|
||||
}
|
||||
`, zoneName, zoneName)
|
||||
}
|
||||
|
||||
func testAccDNSV2RecordSet_readTTL(zoneName string) string {
|
||||
return fmt.Sprintf(`
|
||||
resource "openstack_dns_zone_v2" "zone_1" {
|
||||
name = "%s"
|
||||
email = "email2@example.com"
|
||||
description = "an updated zone"
|
||||
ttl = 6000
|
||||
type = "PRIMARY"
|
||||
}
|
||||
|
||||
resource "openstack_dns_recordset_v2" "recordset_1" {
|
||||
zone_id = "${openstack_dns_zone_v2.zone_1.id}"
|
||||
name = "%s"
|
||||
type = "A"
|
||||
records = ["10.1.0.2"]
|
||||
}
|
||||
`, zoneName, zoneName)
|
||||
}
|
||||
|
||||
func testAccDNSV2RecordSet_timeout(zoneName string) string {
|
||||
return fmt.Sprintf(`
|
||||
resource "openstack_dns_zone_v2" "zone_1" {
|
||||
name = "%s"
|
||||
email = "email2@example.com"
|
||||
description = "an updated zone"
|
||||
ttl = 6000
|
||||
type = "PRIMARY"
|
||||
}
|
||||
|
||||
resource "openstack_dns_recordset_v2" "recordset_1" {
|
||||
zone_id = "${openstack_dns_zone_v2.zone_1.id}"
|
||||
name = "%s"
|
||||
type = "A"
|
||||
ttl = 3000
|
||||
records = ["10.1.0.3"]
|
||||
|
||||
timeouts {
|
||||
create = "5m"
|
||||
update = "5m"
|
||||
delete = "5m"
|
||||
}
|
||||
}
|
||||
`, zoneName, zoneName)
|
||||
}
|
|
@ -180,7 +180,12 @@ func resourceDNSZoneV2Update(d *schema.ResourceData, meta interface{}) error {
|
|||
updateOpts.TTL = d.Get("ttl").(int)
|
||||
}
|
||||
if d.HasChange("masters") {
|
||||
updateOpts.Masters = d.Get("masters").([]string)
|
||||
mastersraw := d.Get("masters").(*schema.Set).List()
|
||||
masters := make([]string, len(mastersraw))
|
||||
for i, masterraw := range mastersraw {
|
||||
masters[i] = masterraw.(string)
|
||||
}
|
||||
updateOpts.Masters = masters
|
||||
}
|
||||
if d.HasChange("description") {
|
||||
updateOpts.Description = d.Get("description").(string)
|
||||
|
|
|
@ -12,6 +12,7 @@ import (
|
|||
|
||||
"github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/keypairs"
|
||||
"github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/servergroups"
|
||||
"github.com/gophercloud/gophercloud/openstack/dns/v2/recordsets"
|
||||
"github.com/gophercloud/gophercloud/openstack/dns/v2/zones"
|
||||
"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/fwaas/firewalls"
|
||||
"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/fwaas/policies"
|
||||
|
@ -225,6 +226,27 @@ func (opts PortCreateOpts) ToPortCreateMap() (map[string]interface{}, error) {
|
|||
return BuildRequest(opts, "port")
|
||||
}
|
||||
|
||||
// RecordSetCreateOpts represents the attributes used when creating a new DNS record set.
|
||||
type RecordSetCreateOpts struct {
|
||||
recordsets.CreateOpts
|
||||
ValueSpecs map[string]string `json:"value_specs,omitempty"`
|
||||
}
|
||||
|
||||
// ToRecordSetCreateMap casts a CreateOpts struct to a map.
|
||||
// It overrides recordsets.ToRecordSetCreateMap to add the ValueSpecs field.
|
||||
func (opts RecordSetCreateOpts) ToRecordSetCreateMap() (map[string]interface{}, error) {
|
||||
b, err := BuildRequest(opts, "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if m, ok := b[""].(map[string]interface{}); ok {
|
||||
return m, nil
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("Expected map but got %T", b[""])
|
||||
}
|
||||
|
||||
// RouterCreateOpts represents the attributes used when creating a new router.
|
||||
type RouterCreateOpts struct {
|
||||
routers.CreateOpts
|
||||
|
|
6
vendor/github.com/gophercloud/gophercloud/openstack/dns/v2/recordsets/doc.go
generated
vendored
Normal file
6
vendor/github.com/gophercloud/gophercloud/openstack/dns/v2/recordsets/doc.go
generated
vendored
Normal file
|
@ -0,0 +1,6 @@
|
|||
// Package recordsets provides information and interaction with the zone API
|
||||
// resource for the OpenStack DNS service.
|
||||
//
|
||||
// For more information, see:
|
||||
// http://developer.openstack.org/api-ref/dns/#recordsets
|
||||
package recordsets
|
157
vendor/github.com/gophercloud/gophercloud/openstack/dns/v2/recordsets/requests.go
generated
vendored
Normal file
157
vendor/github.com/gophercloud/gophercloud/openstack/dns/v2/recordsets/requests.go
generated
vendored
Normal file
|
@ -0,0 +1,157 @@
|
|||
package recordsets
|
||||
|
||||
import (
|
||||
"github.com/gophercloud/gophercloud"
|
||||
"github.com/gophercloud/gophercloud/pagination"
|
||||
)
|
||||
|
||||
// ListOptsBuilder allows extensions to add additional parameters to the
|
||||
// List request.
|
||||
type ListOptsBuilder interface {
|
||||
ToRecordSetListQuery() (string, error)
|
||||
}
|
||||
|
||||
// ListOpts allows the filtering and sorting of paginated collections through
|
||||
// the API. Filtering is achieved by passing in struct field values that map to
|
||||
// the server attributes you want to see returned. Marker and Limit are used
|
||||
// for pagination.
|
||||
// https://developer.openstack.org/api-ref/dns/
|
||||
type ListOpts struct {
|
||||
// Integer value for the limit of values to return.
|
||||
Limit int `q:"limit"`
|
||||
|
||||
// UUID of the recordset at which you want to set a marker.
|
||||
Marker string `q:"marker"`
|
||||
|
||||
Data string `q:"data"`
|
||||
Description string `q:"description"`
|
||||
Name string `q:"name"`
|
||||
SortDir string `q:"sort_dir"`
|
||||
SortKey string `q:"sort_key"`
|
||||
Status string `q:"status"`
|
||||
TTL int `q:"ttl"`
|
||||
Type string `q:"type"`
|
||||
ZoneID string `q:"zone_id"`
|
||||
}
|
||||
|
||||
// ToRecordSetListQuery formats a ListOpts into a query string.
|
||||
func (opts ListOpts) ToRecordSetListQuery() (string, error) {
|
||||
q, err := gophercloud.BuildQueryString(opts)
|
||||
return q.String(), err
|
||||
}
|
||||
|
||||
// ListByZone implements the recordset list request.
|
||||
func ListByZone(client *gophercloud.ServiceClient, zoneID string, opts ListOptsBuilder) pagination.Pager {
|
||||
url := baseURL(client, zoneID)
|
||||
if opts != nil {
|
||||
query, err := opts.ToRecordSetListQuery()
|
||||
if err != nil {
|
||||
return pagination.Pager{Err: err}
|
||||
}
|
||||
url += query
|
||||
}
|
||||
return pagination.NewPager(client, url, func(r pagination.PageResult) pagination.Page {
|
||||
return RecordSetPage{pagination.LinkedPageBase{PageResult: r}}
|
||||
})
|
||||
}
|
||||
|
||||
// Get implements the recordset get request.
|
||||
func Get(client *gophercloud.ServiceClient, zoneID string, rrsetID string) (r GetResult) {
|
||||
_, r.Err = client.Get(rrsetURL(client, zoneID, rrsetID), &r.Body, nil)
|
||||
return
|
||||
}
|
||||
|
||||
// CreateOptsBuilder allows extensions to add additional attributes to the Create request.
|
||||
type CreateOptsBuilder interface {
|
||||
ToRecordSetCreateMap() (map[string]interface{}, error)
|
||||
}
|
||||
|
||||
// CreateOpts specifies the base attributes that may be used to create a RecordSet.
|
||||
type CreateOpts struct {
|
||||
// Name is the name of the RecordSet.
|
||||
Name string `json:"name" required:"true"`
|
||||
|
||||
// Description is a description of the RecordSet.
|
||||
Description string `json:"description,omitempty"`
|
||||
|
||||
// Records are the DNS records of the RecordSet.
|
||||
Records []string `json:"records,omitempty"`
|
||||
|
||||
// TTL is the time to live of the RecordSet.
|
||||
TTL int `json:"ttl,omitempty"`
|
||||
|
||||
// Type is the RRTYPE of the RecordSet.
|
||||
Type string `json:"type,omitempty"`
|
||||
}
|
||||
|
||||
// ToRecordSetCreateMap formats an CreateOpts structure into a request body.
|
||||
func (opts CreateOpts) ToRecordSetCreateMap() (map[string]interface{}, error) {
|
||||
b, err := gophercloud.BuildRequestBody(opts, "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return b, nil
|
||||
}
|
||||
|
||||
// Create creates a recordset in a given zone.
|
||||
func Create(client *gophercloud.ServiceClient, zoneID string, opts CreateOptsBuilder) (r CreateResult) {
|
||||
b, err := opts.ToRecordSetCreateMap()
|
||||
if err != nil {
|
||||
r.Err = err
|
||||
return
|
||||
}
|
||||
_, r.Err = client.Post(baseURL(client, zoneID), &b, &r.Body, &gophercloud.RequestOpts{
|
||||
OkCodes: []int{201, 202},
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// UpdateOptsBuilder allows extensions to add additional attributes to the Update request.
|
||||
type UpdateOptsBuilder interface {
|
||||
ToRecordSetUpdateMap() (map[string]interface{}, error)
|
||||
}
|
||||
|
||||
// UpdateOpts specifies the base attributes that may be updated on an existing RecordSet.
|
||||
type UpdateOpts struct {
|
||||
Description string `json:"description,omitempty"`
|
||||
TTL int `json:"ttl,omitempty"`
|
||||
Records []string `json:"records,omitempty"`
|
||||
}
|
||||
|
||||
// ToRecordSetUpdateMap formats an UpdateOpts structure into a request body.
|
||||
func (opts UpdateOpts) ToRecordSetUpdateMap() (map[string]interface{}, error) {
|
||||
b, err := gophercloud.BuildRequestBody(opts, "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if opts.TTL > 0 {
|
||||
b["ttl"] = opts.TTL
|
||||
} else {
|
||||
b["ttl"] = nil
|
||||
}
|
||||
|
||||
return b, nil
|
||||
}
|
||||
|
||||
// Update updates a recordset in a given zone
|
||||
func Update(client *gophercloud.ServiceClient, zoneID string, rrsetID string, opts UpdateOptsBuilder) (r UpdateResult) {
|
||||
b, err := opts.ToRecordSetUpdateMap()
|
||||
if err != nil {
|
||||
r.Err = err
|
||||
return
|
||||
}
|
||||
_, r.Err = client.Put(rrsetURL(client, zoneID, rrsetID), &b, &r.Body, &gophercloud.RequestOpts{
|
||||
OkCodes: []int{200, 202},
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// Delete removes an existing RecordSet.
|
||||
func Delete(client *gophercloud.ServiceClient, zoneID string, rrsetID string) (r DeleteResult) {
|
||||
_, r.Err = client.Delete(rrsetURL(client, zoneID, rrsetID), &gophercloud.RequestOpts{
|
||||
OkCodes: []int{202},
|
||||
})
|
||||
return
|
||||
}
|
141
vendor/github.com/gophercloud/gophercloud/openstack/dns/v2/recordsets/results.go
generated
vendored
Normal file
141
vendor/github.com/gophercloud/gophercloud/openstack/dns/v2/recordsets/results.go
generated
vendored
Normal file
|
@ -0,0 +1,141 @@
|
|||
package recordsets
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"time"
|
||||
|
||||
"github.com/gophercloud/gophercloud"
|
||||
"github.com/gophercloud/gophercloud/pagination"
|
||||
)
|
||||
|
||||
type commonResult struct {
|
||||
gophercloud.Result
|
||||
}
|
||||
|
||||
// Extract interprets a GetResult, CreateResult or UpdateResult as a concrete RecordSet.
|
||||
// An error is returned if the original call or the extraction failed.
|
||||
func (r commonResult) Extract() (*RecordSet, error) {
|
||||
var s *RecordSet
|
||||
err := r.ExtractInto(&s)
|
||||
return s, err
|
||||
}
|
||||
|
||||
// CreateResult is the deferred result of a Create call.
|
||||
type CreateResult struct {
|
||||
commonResult
|
||||
}
|
||||
|
||||
// GetResult is the deferred result of a Get call.
|
||||
type GetResult struct {
|
||||
commonResult
|
||||
}
|
||||
|
||||
// RecordSetPage is a single page of RecordSet results.
|
||||
type RecordSetPage struct {
|
||||
pagination.LinkedPageBase
|
||||
}
|
||||
|
||||
// UpdateResult is the deferred result of an Update call.
|
||||
type UpdateResult struct {
|
||||
commonResult
|
||||
}
|
||||
|
||||
// DeleteResult is the deferred result of an Delete call.
|
||||
type DeleteResult struct {
|
||||
gophercloud.ErrResult
|
||||
}
|
||||
|
||||
// IsEmpty returns true if the page contains no results.
|
||||
func (r RecordSetPage) IsEmpty() (bool, error) {
|
||||
s, err := ExtractRecordSets(r)
|
||||
return len(s) == 0, err
|
||||
}
|
||||
|
||||
// ExtractRecordSets extracts a slice of RecordSets from a Collection acquired from List.
|
||||
func ExtractRecordSets(r pagination.Page) ([]RecordSet, error) {
|
||||
var s struct {
|
||||
RecordSets []RecordSet `json:"recordsets"`
|
||||
}
|
||||
err := (r.(RecordSetPage)).ExtractInto(&s)
|
||||
return s.RecordSets, err
|
||||
}
|
||||
|
||||
type RecordSet struct {
|
||||
// ID is the unique ID of the recordset
|
||||
ID string `json:"id"`
|
||||
|
||||
// ZoneID is the ID of the zone the recordset belongs to.
|
||||
ZoneID string `json:"zone_id"`
|
||||
|
||||
// ProjectID is the ID of the project that owns the recordset.
|
||||
ProjectID string `json:"project_id"`
|
||||
|
||||
// Name is the name of the recordset.
|
||||
Name string `json:"name"`
|
||||
|
||||
// ZoneName is the name of the zone the recordset belongs to.
|
||||
ZoneName string `json:"zone_name"`
|
||||
|
||||
// Type is the RRTYPE of the recordset.
|
||||
Type string `json:"type"`
|
||||
|
||||
// Records are the DNS records of the recordset.
|
||||
Records []string `json:"records"`
|
||||
|
||||
// TTL is the time to live of the recordset.
|
||||
TTL int `json:"ttl"`
|
||||
|
||||
// Status is the status of the recordset.
|
||||
Status string `json:"status"`
|
||||
|
||||
// Action is the current action in progress of the recordset.
|
||||
Action string `json:"action"`
|
||||
|
||||
// Description is the description of the recordset.
|
||||
Description string `json:"description"`
|
||||
|
||||
// Version is the revision of the recordset.
|
||||
Version int `json:version"`
|
||||
|
||||
// CreatedAt is the date when the recordset was created.
|
||||
CreatedAt time.Time `json:"-"`
|
||||
|
||||
// UpdatedAt is the date when the recordset was updated.
|
||||
UpdatedAt time.Time `json:"-"`
|
||||
|
||||
// Links includes HTTP references to the itself,
|
||||
// useful for passing along to other APIs that might want a recordset reference.
|
||||
Links []gophercloud.Link `json:"-"`
|
||||
}
|
||||
|
||||
func (r *RecordSet) UnmarshalJSON(b []byte) error {
|
||||
type tmp RecordSet
|
||||
var s struct {
|
||||
tmp
|
||||
CreatedAt gophercloud.JSONRFC3339MilliNoZ `json:"created_at"`
|
||||
UpdatedAt gophercloud.JSONRFC3339MilliNoZ `json:"updated_at"`
|
||||
Links map[string]interface{} `json:"links"`
|
||||
}
|
||||
err := json.Unmarshal(b, &s)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*r = RecordSet(s.tmp)
|
||||
|
||||
r.CreatedAt = time.Time(s.CreatedAt)
|
||||
r.UpdatedAt = time.Time(s.UpdatedAt)
|
||||
|
||||
if s.Links != nil {
|
||||
for rel, href := range s.Links {
|
||||
if v, ok := href.(string); ok {
|
||||
link := gophercloud.Link{
|
||||
Rel: rel,
|
||||
Href: v,
|
||||
}
|
||||
r.Links = append(r.Links, link)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
11
vendor/github.com/gophercloud/gophercloud/openstack/dns/v2/recordsets/urls.go
generated
vendored
Normal file
11
vendor/github.com/gophercloud/gophercloud/openstack/dns/v2/recordsets/urls.go
generated
vendored
Normal file
|
@ -0,0 +1,11 @@
|
|||
package recordsets
|
||||
|
||||
import "github.com/gophercloud/gophercloud"
|
||||
|
||||
func baseURL(c *gophercloud.ServiceClient, zoneID string) string {
|
||||
return c.ServiceURL("zones", zoneID, "recordsets")
|
||||
}
|
||||
|
||||
func rrsetURL(c *gophercloud.ServiceClient, zoneID string, rrsetID string) string {
|
||||
return c.ServiceURL("zones", zoneID, "recordsets", rrsetID)
|
||||
}
|
|
@ -1714,6 +1714,12 @@
|
|||
"revision": "0f64da0e36de86a0ca1a8f2fc1b0570a0d3f7504",
|
||||
"revisionTime": "2017-03-10T01:59:53Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "Mugw0ROrabHNN4nG9YlimPbyENk=",
|
||||
"path": "github.com/gophercloud/gophercloud/openstack/dns/v2/recordsets",
|
||||
"revision": "5a6e13341e63bd202a0da558a2a7187720042676",
|
||||
"revisionTime": "2017-05-22T01:35:44Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "OGb3suDcMij0bnu0r/eQgWAX5Ho=",
|
||||
"path": "github.com/gophercloud/gophercloud/openstack/dns/v2/zones",
|
||||
|
|
|
@ -0,0 +1,82 @@
|
|||
---
|
||||
layout: "openstack"
|
||||
page_title: "OpenStack: openstack_dns_recordset_v2"
|
||||
sidebar_current: "docs-openstack-resource-dns-recordset-v2"
|
||||
description: |-
|
||||
Manages a DNS record set in the OpenStack DNS Service
|
||||
---
|
||||
|
||||
# openstack\_dns\_recordset_v2
|
||||
|
||||
Manages a DNS record set in the OpenStack DNS Service.
|
||||
|
||||
## Example Usage
|
||||
|
||||
### Automatically detect the correct network
|
||||
|
||||
```hcl
|
||||
resource "openstack_dns_zone_v2" "example_zone" {
|
||||
name = "example.com."
|
||||
email = "email2@example.com"
|
||||
description = "a zone"
|
||||
ttl = 6000
|
||||
type = "PRIMARY"
|
||||
}
|
||||
|
||||
resource "openstack_dns_recordset_v2" "rs_example_com" {
|
||||
zone_id = "${openstack_dns_zone_v2.example_zone.id}"
|
||||
name = "rs.example.com."
|
||||
description = "An example record set"
|
||||
ttl = 3000
|
||||
type = "A"
|
||||
records = ["10.0.0.1"]
|
||||
}
|
||||
```
|
||||
|
||||
## Argument Reference
|
||||
|
||||
The following arguments are supported:
|
||||
|
||||
* `region` - (Required) The region in which to obtain the V2 DNS client.
|
||||
If omitted, the `OS_REGION_NAME` environment variable is used.
|
||||
Changing this creates a new DNS record set.
|
||||
|
||||
* `zone_id` - (Required) The ID of the zone in which to create the record set.
|
||||
Changing this creates a new DNS record set.
|
||||
|
||||
* `name` - (Required) The name of the record set. Note the `.` at the end of the name.
|
||||
Changing this creates a new DNS record set.
|
||||
|
||||
* `type` - (Optional) The type of record set. Examples: "A", "MX".
|
||||
Changing this creates a new DNS record set.
|
||||
|
||||
* `ttl` - (Optional) The time to live (TTL) of the record set.
|
||||
|
||||
* `description` - (Optional) A description of the record set.
|
||||
|
||||
* `records` - (Optional) An array of DNS records.
|
||||
|
||||
* `value_specs` - (Optional) Map of additional options. Changing this creates a
|
||||
new record set.
|
||||
|
||||
## Attributes Reference
|
||||
|
||||
The following attributes are exported:
|
||||
|
||||
* `region` - See Argument Reference above.
|
||||
* `name` - See Argument Reference above.
|
||||
* `type` - See Argument Reference above.
|
||||
* `ttl` - See Argument Reference above.
|
||||
* `description` - See Argument Reference above.
|
||||
* `records` - See Argument Reference above.
|
||||
* `zone_id` - See Argument Reference above.
|
||||
* `value_specs` - See Argument Reference above.
|
||||
|
||||
## Import
|
||||
|
||||
This resource can be imported by specifying the zone ID and recordset ID,
|
||||
separated by a forward slash.
|
||||
|
||||
```
|
||||
$ terraform import openstack_dns_recordset_v2.recordset_1 <zone_id>/<recordset_id>
|
||||
```
|
Loading…
Reference in New Issue