Merge pull request #3333 from aybabtme/use-official-digitalocean-client

use official Go client for DigitalOcean provider
This commit is contained in:
Paul Hinze 2015-10-16 09:11:04 -05:00
commit b171d75adb
9 changed files with 311 additions and 173 deletions

View File

@ -3,7 +3,8 @@ package digitalocean
import (
"log"
"github.com/pearkes/digitalocean"
"github.com/digitalocean/godo"
"golang.org/x/oauth2"
)
type Config struct {
@ -11,14 +12,14 @@ type Config struct {
}
// Client() returns a new client for accessing digital ocean.
func (c *Config) Client() (*digitalocean.Client, error) {
client, err := digitalocean.NewClient(c.Token)
func (c *Config) Client() (*godo.Client, error) {
tokenSrc := oauth2.StaticTokenSource(&oauth2.Token{
AccessToken: c.Token,
})
log.Printf("[INFO] DigitalOcean Client configured for URL: %s", client.URL)
client := godo.NewClient(oauth2.NewClient(oauth2.NoContext, tokenSrc))
if err != nil {
return nil, err
}
log.Printf("[INFO] DigitalOcean Client configured for URL: %s", client.BaseURL.String())
return client, nil
}

View File

@ -5,8 +5,8 @@ import (
"log"
"strings"
"github.com/digitalocean/godo"
"github.com/hashicorp/terraform/helper/schema"
"github.com/pearkes/digitalocean"
)
func resourceDigitalOceanDomain() *schema.Resource {
@ -32,30 +32,31 @@ func resourceDigitalOceanDomain() *schema.Resource {
}
func resourceDigitalOceanDomainCreate(d *schema.ResourceData, meta interface{}) error {
client := meta.(*digitalocean.Client)
client := meta.(*godo.Client)
// Build up our creation options
opts := &digitalocean.CreateDomain{
opts := &godo.DomainCreateRequest{
Name: d.Get("name").(string),
IPAddress: d.Get("ip_address").(string),
}
log.Printf("[DEBUG] Domain create configuration: %#v", opts)
name, err := client.CreateDomain(opts)
domain, _, err := client.Domains.Create(opts)
if err != nil {
return fmt.Errorf("Error creating Domain: %s", err)
}
d.SetId(name)
log.Printf("[INFO] Domain Name: %s", name)
d.SetId(domain.Name)
log.Printf("[INFO] Domain Name: %s", domain.Name)
return resourceDigitalOceanDomainRead(d, meta)
}
func resourceDigitalOceanDomainRead(d *schema.ResourceData, meta interface{}) error {
client := meta.(*digitalocean.Client)
client := meta.(*godo.Client)
domain, err := client.RetrieveDomain(d.Id())
domain, _, err := client.Domains.Get(d.Id())
if err != nil {
// If the domain is somehow already destroyed, mark as
// successfully gone
@ -73,10 +74,10 @@ func resourceDigitalOceanDomainRead(d *schema.ResourceData, meta interface{}) er
}
func resourceDigitalOceanDomainDelete(d *schema.ResourceData, meta interface{}) error {
client := meta.(*digitalocean.Client)
client := meta.(*godo.Client)
log.Printf("[INFO] Deleting Domain: %s", d.Id())
err := client.DestroyDomain(d.Id())
_, err := client.Domains.Delete(d.Id())
if err != nil {
return fmt.Errorf("Error deleting Domain: %s", err)
}

View File

@ -4,13 +4,13 @@ import (
"fmt"
"testing"
"github.com/digitalocean/godo"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
"github.com/pearkes/digitalocean"
)
func TestAccDigitalOceanDomain_Basic(t *testing.T) {
var domain digitalocean.Domain
var domain godo.Domain
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
@ -33,7 +33,7 @@ func TestAccDigitalOceanDomain_Basic(t *testing.T) {
}
func testAccCheckDigitalOceanDomainDestroy(s *terraform.State) error {
client := testAccProvider.Meta().(*digitalocean.Client)
client := testAccProvider.Meta().(*godo.Client)
for _, rs := range s.RootModule().Resources {
if rs.Type != "digitalocean_domain" {
@ -41,17 +41,17 @@ func testAccCheckDigitalOceanDomainDestroy(s *terraform.State) error {
}
// Try to find the domain
_, err := client.RetrieveDomain(rs.Primary.ID)
_, _, err := client.Domains.Get(rs.Primary.ID)
if err == nil {
fmt.Errorf("Domain still exists")
return fmt.Errorf("Domain still exists")
}
}
return nil
}
func testAccCheckDigitalOceanDomainAttributes(domain *digitalocean.Domain) resource.TestCheckFunc {
func testAccCheckDigitalOceanDomainAttributes(domain *godo.Domain) resource.TestCheckFunc {
return func(s *terraform.State) error {
if domain.Name != "foobar-test-terraform.com" {
@ -62,7 +62,7 @@ func testAccCheckDigitalOceanDomainAttributes(domain *digitalocean.Domain) resou
}
}
func testAccCheckDigitalOceanDomainExists(n string, domain *digitalocean.Domain) resource.TestCheckFunc {
func testAccCheckDigitalOceanDomainExists(n string, domain *godo.Domain) resource.TestCheckFunc {
return func(s *terraform.State) error {
rs, ok := s.RootModule().Resources[n]
@ -74,9 +74,9 @@ func testAccCheckDigitalOceanDomainExists(n string, domain *digitalocean.Domain)
return fmt.Errorf("No Record ID is set")
}
client := testAccProvider.Meta().(*digitalocean.Client)
client := testAccProvider.Meta().(*godo.Client)
foundDomain, err := client.RetrieveDomain(rs.Primary.ID)
foundDomain, _, err := client.Domains.Get(rs.Primary.ID)
if err != nil {
return err
@ -86,7 +86,7 @@ func testAccCheckDigitalOceanDomainExists(n string, domain *digitalocean.Domain)
return fmt.Errorf("Record not found")
}
*domain = foundDomain
*domain = *foundDomain
return nil
}

View File

@ -3,12 +3,13 @@ package digitalocean
import (
"fmt"
"log"
"strconv"
"strings"
"time"
"github.com/digitalocean/godo"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/helper/schema"
"github.com/pearkes/digitalocean"
)
func resourceDigitalOceanDroplet() *schema.Resource {
@ -105,11 +106,13 @@ func resourceDigitalOceanDroplet() *schema.Resource {
}
func resourceDigitalOceanDropletCreate(d *schema.ResourceData, meta interface{}) error {
client := meta.(*digitalocean.Client)
client := meta.(*godo.Client)
// Build up our creation options
opts := &digitalocean.CreateDroplet{
Image: d.Get("image").(string),
opts := &godo.DropletCreateRequest{
Image: godo.DropletCreateImage{
Slug: d.Get("image").(string),
},
Name: d.Get("name").(string),
Region: d.Get("region").(string),
Size: d.Get("size").(string),
@ -120,7 +123,7 @@ func resourceDigitalOceanDropletCreate(d *schema.ResourceData, meta interface{})
}
if attr, ok := d.GetOk("ipv6"); ok {
opts.IPV6 = attr.(bool)
opts.IPv6 = attr.(bool)
}
if attr, ok := d.GetOk("private_networking"); ok {
@ -132,25 +135,32 @@ func resourceDigitalOceanDropletCreate(d *schema.ResourceData, meta interface{})
}
// Get configured ssh_keys
ssh_keys := d.Get("ssh_keys.#").(int)
if ssh_keys > 0 {
opts.SSHKeys = make([]string, 0, ssh_keys)
for i := 0; i < ssh_keys; i++ {
sshKeys := d.Get("ssh_keys.#").(int)
if sshKeys > 0 {
opts.SSHKeys = make([]godo.DropletCreateSSHKey, 0, sshKeys)
for i := 0; i < sshKeys; i++ {
key := fmt.Sprintf("ssh_keys.%d", i)
opts.SSHKeys = append(opts.SSHKeys, d.Get(key).(string))
id, err := strconv.Atoi(d.Get(key).(string))
if err != nil {
return err
}
opts.SSHKeys = append(opts.SSHKeys, godo.DropletCreateSSHKey{
ID: id,
})
}
}
log.Printf("[DEBUG] Droplet create configuration: %#v", opts)
id, err := client.CreateDroplet(opts)
droplet, _, err := client.Droplets.Create(opts)
if err != nil {
return fmt.Errorf("Error creating droplet: %s", err)
}
// Assign the droplets id
d.SetId(id)
d.SetId(strconv.Itoa(droplet.ID))
log.Printf("[INFO] Droplet ID: %s", d.Id())
@ -164,10 +174,15 @@ func resourceDigitalOceanDropletCreate(d *schema.ResourceData, meta interface{})
}
func resourceDigitalOceanDropletRead(d *schema.ResourceData, meta interface{}) error {
client := meta.(*digitalocean.Client)
client := meta.(*godo.Client)
id, err := strconv.Atoi(d.Id())
if err != nil {
return fmt.Errorf("invalid droplet id: %v", err)
}
// Retrieve the droplet properties for updating the state
droplet, err := client.RetrieveDroplet(d.Id())
droplet, _, err := client.Droplets.Get(id)
if err != nil {
// check if the droplet no longer exists.
if err.Error() == "Error retrieving droplet: API Error: 404 Not Found" {
@ -178,48 +193,70 @@ func resourceDigitalOceanDropletRead(d *schema.ResourceData, meta interface{}) e
return fmt.Errorf("Error retrieving droplet: %s", err)
}
if droplet.ImageSlug() != "" {
d.Set("image", droplet.ImageSlug())
if droplet.Image.Slug != "" {
d.Set("image", droplet.Image.Slug)
} else {
d.Set("image", droplet.ImageId())
d.Set("image", droplet.Image.ID)
}
d.Set("name", droplet.Name)
d.Set("region", droplet.RegionSlug())
d.Set("size", droplet.SizeSlug)
d.Set("region", droplet.Region.Slug)
d.Set("size", droplet.Size.Slug)
d.Set("status", droplet.Status)
d.Set("locked", droplet.IsLocked())
d.Set("locked", strconv.FormatBool(droplet.Locked))
if droplet.IPV6Address("public") != "" {
if publicIPv6 := findIPv6AddrByType(droplet, "public"); publicIPv6 != "" {
d.Set("ipv6", true)
d.Set("ipv6_address", droplet.IPV6Address("public"))
d.Set("ipv6_address_private", droplet.IPV6Address("private"))
d.Set("ipv6_address", publicIPv6)
d.Set("ipv6_address_private", findIPv6AddrByType(droplet, "private"))
}
d.Set("ipv4_address", droplet.IPV4Address("public"))
d.Set("ipv4_address", findIPv4AddrByType(droplet, "public"))
if droplet.NetworkingType() == "private" {
if privateIPv4 := findIPv4AddrByType(droplet, "private"); privateIPv4 != "" {
d.Set("private_networking", true)
d.Set("ipv4_address_private", droplet.IPV4Address("private"))
d.Set("ipv4_address_private", privateIPv4)
}
// Initialize the connection info
d.SetConnInfo(map[string]string{
"type": "ssh",
"host": droplet.IPV4Address("public"),
"host": findIPv4AddrByType(droplet, "public"),
})
return nil
}
func findIPv6AddrByType(d *godo.Droplet, addrType string) string {
for _, addr := range d.Networks.V6 {
if addr.Type == addrType {
return addr.IPAddress
}
}
return ""
}
func findIPv4AddrByType(d *godo.Droplet, addrType string) string {
for _, addr := range d.Networks.V4 {
if addr.Type == addrType {
return addr.IPAddress
}
}
return ""
}
func resourceDigitalOceanDropletUpdate(d *schema.ResourceData, meta interface{}) error {
client := meta.(*digitalocean.Client)
client := meta.(*godo.Client)
id, err := strconv.Atoi(d.Id())
if err != nil {
return fmt.Errorf("invalid droplet id: %v", err)
}
if d.HasChange("size") {
oldSize, newSize := d.GetChange("size")
err := client.PowerOff(d.Id())
_, _, err = client.DropletActions.PowerOff(id)
if err != nil && !strings.Contains(err.Error(), "Droplet is already powered off") {
return fmt.Errorf(
"Error powering off droplet (%s): %s", d.Id(), err)
@ -233,7 +270,7 @@ func resourceDigitalOceanDropletUpdate(d *schema.ResourceData, meta interface{})
}
// Resize the droplet
err = client.Resize(d.Id(), newSize.(string))
_, _, err = client.DropletActions.Resize(id, newSize.(string), true)
if err != nil {
newErr := powerOnAndWait(d, meta)
if newErr != nil {
@ -258,7 +295,7 @@ func resourceDigitalOceanDropletUpdate(d *schema.ResourceData, meta interface{})
"Error waiting for resize droplet (%s) to finish: %s", d.Id(), err)
}
err = client.PowerOn(d.Id())
_, _, err = client.DropletActions.PowerOn(id)
if err != nil {
return fmt.Errorf(
@ -276,7 +313,7 @@ func resourceDigitalOceanDropletUpdate(d *schema.ResourceData, meta interface{})
oldName, newName := d.GetChange("name")
// Rename the droplet
err := client.Rename(d.Id(), newName.(string))
_, _, err = client.DropletActions.Rename(id, newName.(string))
if err != nil {
return fmt.Errorf(
@ -296,7 +333,7 @@ func resourceDigitalOceanDropletUpdate(d *schema.ResourceData, meta interface{})
// As there is no way to disable private networking,
// we only check if it needs to be enabled
if d.HasChange("private_networking") && d.Get("private_networking").(bool) {
err := client.EnablePrivateNetworking(d.Id())
_, _, err = client.DropletActions.EnablePrivateNetworking(id)
if err != nil {
return fmt.Errorf(
@ -313,7 +350,7 @@ func resourceDigitalOceanDropletUpdate(d *schema.ResourceData, meta interface{})
// As there is no way to disable IPv6, we only check if it needs to be enabled
if d.HasChange("ipv6") && d.Get("ipv6").(bool) {
err := client.EnableIPV6s(d.Id())
_, _, err = client.DropletActions.EnableIPv6(id)
if err != nil {
return fmt.Errorf(
@ -334,9 +371,14 @@ func resourceDigitalOceanDropletUpdate(d *schema.ResourceData, meta interface{})
}
func resourceDigitalOceanDropletDelete(d *schema.ResourceData, meta interface{}) error {
client := meta.(*digitalocean.Client)
client := meta.(*godo.Client)
_, err := WaitForDropletAttribute(
id, err := strconv.Atoi(d.Id())
if err != nil {
return fmt.Errorf("invalid droplet id: %v", err)
}
_, err = WaitForDropletAttribute(
d, "false", []string{"", "true"}, "locked", meta)
if err != nil {
@ -347,7 +389,7 @@ func resourceDigitalOceanDropletDelete(d *schema.ResourceData, meta interface{})
log.Printf("[INFO] Deleting droplet: %s", d.Id())
// Destroy the droplet
err = client.DestroyDroplet(d.Id())
_, err = client.Droplets.Delete(id)
// Handle remotely destroyed droplets
if err != nil && strings.Contains(err.Error(), "404 Not Found") {
@ -390,9 +432,14 @@ func WaitForDropletAttribute(
// cleaner and more efficient
func newDropletStateRefreshFunc(
d *schema.ResourceData, attribute string, meta interface{}) resource.StateRefreshFunc {
client := meta.(*digitalocean.Client)
client := meta.(*godo.Client)
return func() (interface{}, string, error) {
err := resourceDigitalOceanDropletRead(d, meta)
id, err := strconv.Atoi(d.Id())
if err != nil {
return nil, "", err
}
err = resourceDigitalOceanDropletRead(d, meta)
if err != nil {
return nil, "", err
}
@ -408,7 +455,7 @@ func newDropletStateRefreshFunc(
// See if we can access our attribute
if attr, ok := d.GetOk(attribute); ok {
// Retrieve the droplet properties
droplet, err := client.RetrieveDroplet(d.Id())
droplet, _, err := client.Droplets.Get(id)
if err != nil {
return nil, "", fmt.Errorf("Error retrieving droplet: %s", err)
}
@ -422,8 +469,13 @@ func newDropletStateRefreshFunc(
// Powers on the droplet and waits for it to be active
func powerOnAndWait(d *schema.ResourceData, meta interface{}) error {
client := meta.(*digitalocean.Client)
err := client.PowerOn(d.Id())
id, err := strconv.Atoi(d.Id())
if err != nil {
return fmt.Errorf("invalid droplet id: %v", err)
}
client := meta.(*godo.Client)
_, _, err = client.DropletActions.PowerOn(id)
if err != nil {
return err
}

View File

@ -2,16 +2,17 @@ package digitalocean
import (
"fmt"
"strconv"
"strings"
"testing"
"github.com/digitalocean/godo"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
"github.com/pearkes/digitalocean"
)
func TestAccDigitalOceanDroplet_Basic(t *testing.T) {
var droplet digitalocean.Droplet
var droplet godo.Droplet
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
@ -40,7 +41,7 @@ func TestAccDigitalOceanDroplet_Basic(t *testing.T) {
}
func TestAccDigitalOceanDroplet_Update(t *testing.T) {
var droplet digitalocean.Droplet
var droplet godo.Droplet
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
@ -71,7 +72,7 @@ func TestAccDigitalOceanDroplet_Update(t *testing.T) {
}
func TestAccDigitalOceanDroplet_PrivateNetworkingIpv6(t *testing.T) {
var droplet digitalocean.Droplet
var droplet godo.Droplet
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
@ -94,15 +95,20 @@ func TestAccDigitalOceanDroplet_PrivateNetworkingIpv6(t *testing.T) {
}
func testAccCheckDigitalOceanDropletDestroy(s *terraform.State) error {
client := testAccProvider.Meta().(*digitalocean.Client)
client := testAccProvider.Meta().(*godo.Client)
for _, rs := range s.RootModule().Resources {
if rs.Type != "digitalocean_droplet" {
continue
}
id, err := strconv.Atoi(rs.Primary.ID)
if err != nil {
return err
}
// Try to find the Droplet
_, err := client.RetrieveDroplet(rs.Primary.ID)
_, _, err = client.Droplets.Get(id)
// Wait
@ -116,19 +122,19 @@ func testAccCheckDigitalOceanDropletDestroy(s *terraform.State) error {
return nil
}
func testAccCheckDigitalOceanDropletAttributes(droplet *digitalocean.Droplet) resource.TestCheckFunc {
func testAccCheckDigitalOceanDropletAttributes(droplet *godo.Droplet) resource.TestCheckFunc {
return func(s *terraform.State) error {
if droplet.ImageSlug() != "centos-5-8-x32" {
return fmt.Errorf("Bad image_slug: %s", droplet.ImageSlug())
if droplet.Image.Slug != "centos-5-8-x32" {
return fmt.Errorf("Bad image_slug: %s", droplet.Image.Slug)
}
if droplet.SizeSlug != "512mb" {
return fmt.Errorf("Bad size_slug: %s", droplet.SizeSlug)
if droplet.Size.Slug != "512mb" {
return fmt.Errorf("Bad size_slug: %s", droplet.Size.Slug)
}
if droplet.RegionSlug() != "nyc3" {
return fmt.Errorf("Bad region_slug: %s", droplet.RegionSlug())
if droplet.Region.Slug != "nyc3" {
return fmt.Errorf("Bad region_slug: %s", droplet.Region.Slug)
}
if droplet.Name != "foo" {
@ -138,10 +144,10 @@ func testAccCheckDigitalOceanDropletAttributes(droplet *digitalocean.Droplet) re
}
}
func testAccCheckDigitalOceanDropletRenamedAndResized(droplet *digitalocean.Droplet) resource.TestCheckFunc {
func testAccCheckDigitalOceanDropletRenamedAndResized(droplet *godo.Droplet) resource.TestCheckFunc {
return func(s *terraform.State) error {
if droplet.SizeSlug != "1gb" {
if droplet.Size.Slug != "1gb" {
return fmt.Errorf("Bad size_slug: %s", droplet.SizeSlug)
}
@ -153,50 +159,46 @@ func testAccCheckDigitalOceanDropletRenamedAndResized(droplet *digitalocean.Drop
}
}
func testAccCheckDigitalOceanDropletAttributes_PrivateNetworkingIpv6(droplet *digitalocean.Droplet) resource.TestCheckFunc {
func testAccCheckDigitalOceanDropletAttributes_PrivateNetworkingIpv6(droplet *godo.Droplet) resource.TestCheckFunc {
return func(s *terraform.State) error {
if droplet.ImageSlug() != "centos-5-8-x32" {
return fmt.Errorf("Bad image_slug: %s", droplet.ImageSlug())
if droplet.Image.Slug != "centos-5-8-x32" {
return fmt.Errorf("Bad image_slug: %s", droplet.Image.Slug)
}
if droplet.SizeSlug != "1gb" {
return fmt.Errorf("Bad size_slug: %s", droplet.SizeSlug)
if droplet.Size.Slug != "1gb" {
return fmt.Errorf("Bad size_slug: %s", droplet.Size.Slug)
}
if droplet.RegionSlug() != "sgp1" {
return fmt.Errorf("Bad region_slug: %s", droplet.RegionSlug())
if droplet.Region.Slug != "sgp1" {
return fmt.Errorf("Bad region_slug: %s", droplet.Region.Slug)
}
if droplet.Name != "baz" {
return fmt.Errorf("Bad name: %s", droplet.Name)
}
if droplet.IPV4Address("private") == "" {
return fmt.Errorf("No ipv4 private: %s", droplet.IPV4Address("private"))
if findIPv4AddrByType(droplet, "private") == "" {
return fmt.Errorf("No ipv4 private: %s", findIPv4AddrByType(droplet, "private"))
}
// if droplet.IPV6Address("private") == "" {
// return fmt.Errorf("No ipv6 private: %s", droplet.IPV6Address("private"))
// }
if droplet.NetworkingType() != "private" {
return fmt.Errorf("Bad networking type: %s", droplet.NetworkingType())
if findIPv4AddrByType(droplet, "public") == "" {
return fmt.Errorf("No ipv4 public: %s", findIPv4AddrByType(droplet, "public"))
}
if droplet.IPV4Address("public") == "" {
return fmt.Errorf("No ipv4 public: %s", droplet.IPV4Address("public"))
}
if droplet.IPV6Address("public") == "" {
return fmt.Errorf("No ipv6 public: %s", droplet.IPV6Address("public"))
if findIPv6AddrByType(droplet, "public") == "" {
return fmt.Errorf("No ipv6 public: %s", findIPv6AddrByType(droplet, "public"))
}
return nil
}
}
func testAccCheckDigitalOceanDropletExists(n string, droplet *digitalocean.Droplet) resource.TestCheckFunc {
func testAccCheckDigitalOceanDropletExists(n string, droplet *godo.Droplet) resource.TestCheckFunc {
return func(s *terraform.State) error {
rs, ok := s.RootModule().Resources[n]
if !ok {
@ -207,19 +209,25 @@ func testAccCheckDigitalOceanDropletExists(n string, droplet *digitalocean.Dropl
return fmt.Errorf("No Droplet ID is set")
}
client := testAccProvider.Meta().(*digitalocean.Client)
client := testAccProvider.Meta().(*godo.Client)
retrieveDroplet, err := client.RetrieveDroplet(rs.Primary.ID)
id, err := strconv.Atoi(rs.Primary.ID)
if err != nil {
return err
}
// Try to find the Droplet
retrieveDroplet, _, err := client.Droplets.Get(id)
if err != nil {
return err
}
if retrieveDroplet.StringId() != rs.Primary.ID {
if strconv.Itoa(retrieveDroplet.ID) != rs.Primary.ID {
return fmt.Errorf("Droplet not found")
}
*droplet = retrieveDroplet
*droplet = *retrieveDroplet
return nil
}
@ -230,7 +238,7 @@ func testAccCheckDigitalOceanDropletExists(n string, droplet *digitalocean.Dropl
// other test already
//
//func Test_new_droplet_state_refresh_func(t *testing.T) {
// droplet := digitalocean.Droplet{
// droplet := godo.Droplet{
// Name: "foobar",
// }
// resourceMap, _ := resource_digitalocean_droplet_update_state(

View File

@ -3,10 +3,11 @@ package digitalocean
import (
"fmt"
"log"
"strconv"
"strings"
"github.com/digitalocean/godo"
"github.com/hashicorp/terraform/helper/schema"
"github.com/pearkes/digitalocean"
)
func resourceDigitalOceanRecord() *schema.Resource {
@ -66,34 +67,55 @@ func resourceDigitalOceanRecord() *schema.Resource {
}
func resourceDigitalOceanRecordCreate(d *schema.ResourceData, meta interface{}) error {
client := meta.(*digitalocean.Client)
client := meta.(*godo.Client)
newRecord := digitalocean.CreateRecord{
Type: d.Get("type").(string),
Name: d.Get("name").(string),
Data: d.Get("value").(string),
Priority: d.Get("priority").(string),
Port: d.Get("port").(string),
Weight: d.Get("weight").(string),
newRecord := godo.DomainRecordEditRequest{
Type: d.Get("type").(string),
Name: d.Get("name").(string),
Data: d.Get("value").(string),
}
var err error
if priority := d.Get("priority").(string); priority != "" {
newRecord.Priority, err = strconv.Atoi(priority)
if err != nil {
return fmt.Errorf("Failed to parse priority as an integer: %v", err)
}
}
if port := d.Get("port").(string); port != "" {
newRecord.Port, err = strconv.Atoi(port)
if err != nil {
return fmt.Errorf("Failed to parse port as an integer: %v", err)
}
}
if weight := d.Get("weight").(string); weight != "" {
newRecord.Weight, err = strconv.Atoi(weight)
if err != nil {
return fmt.Errorf("Failed to parse weight as an integer: %v", err)
}
}
log.Printf("[DEBUG] record create configuration: %#v", newRecord)
recId, err := client.CreateRecord(d.Get("domain").(string), &newRecord)
rec, _, err := client.Domains.CreateRecord(d.Get("domain").(string), &newRecord)
if err != nil {
return fmt.Errorf("Failed to create record: %s", err)
}
d.SetId(recId)
d.SetId(strconv.Itoa(rec.ID))
log.Printf("[INFO] Record ID: %s", d.Id())
return resourceDigitalOceanRecordRead(d, meta)
}
func resourceDigitalOceanRecordRead(d *schema.ResourceData, meta interface{}) error {
client := meta.(*digitalocean.Client)
client := meta.(*godo.Client)
domain := d.Get("domain").(string)
id, err := strconv.Atoi(d.Id())
if err != nil {
return fmt.Errorf("invalid record ID: %v", err)
}
rec, err := client.RetrieveRecord(domain, d.Id())
rec, _, err := client.Domains.Record(domain, id)
if err != nil {
// If the record is somehow already destroyed, mark as
// successfully gone
@ -120,23 +142,29 @@ func resourceDigitalOceanRecordRead(d *schema.ResourceData, meta interface{}) er
d.Set("name", rec.Name)
d.Set("type", rec.Type)
d.Set("value", rec.Data)
d.Set("weight", rec.StringWeight())
d.Set("priority", rec.StringPriority())
d.Set("port", rec.StringPort())
d.Set("weight", strconv.Itoa(rec.Weight))
d.Set("priority", strconv.Itoa(rec.Priority))
d.Set("port", strconv.Itoa(rec.Port))
return nil
}
func resourceDigitalOceanRecordUpdate(d *schema.ResourceData, meta interface{}) error {
client := meta.(*digitalocean.Client)
client := meta.(*godo.Client)
var updateRecord digitalocean.UpdateRecord
if v, ok := d.GetOk("name"); ok {
updateRecord.Name = v.(string)
domain := d.Get("domain").(string)
id, err := strconv.Atoi(d.Id())
if err != nil {
return fmt.Errorf("invalid record ID: %v", err)
}
log.Printf("[DEBUG] record update configuration: %#v", updateRecord)
err := client.UpdateRecord(d.Get("domain").(string), d.Id(), &updateRecord)
var editRecord godo.DomainRecordEditRequest
if v, ok := d.GetOk("name"); ok {
editRecord.Name = v.(string)
}
log.Printf("[DEBUG] record update configuration: %#v", editRecord)
_, _, err = client.Domains.EditRecord(domain, id, &editRecord)
if err != nil {
return fmt.Errorf("Failed to update record: %s", err)
}
@ -145,11 +173,17 @@ func resourceDigitalOceanRecordUpdate(d *schema.ResourceData, meta interface{})
}
func resourceDigitalOceanRecordDelete(d *schema.ResourceData, meta interface{}) error {
client := meta.(*digitalocean.Client)
client := meta.(*godo.Client)
log.Printf(
"[INFO] Deleting record: %s, %s", d.Get("domain").(string), d.Id())
err := client.DestroyRecord(d.Get("domain").(string), d.Id())
domain := d.Get("domain").(string)
id, err := strconv.Atoi(d.Id())
if err != nil {
return fmt.Errorf("invalid record ID: %v", err)
}
log.Printf("[INFO] Deleting record: %s, %d", domain, id)
_, err = client.Domains.DeleteRecord(domain, id)
if err != nil {
// If the record is somehow already destroyed, mark as
// successfully gone

View File

@ -2,15 +2,16 @@ package digitalocean
import (
"fmt"
"strconv"
"testing"
"github.com/digitalocean/godo"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
"github.com/pearkes/digitalocean"
)
func TestAccDigitalOceanRecord_Basic(t *testing.T) {
var record digitalocean.Record
var record godo.DomainRecord
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
@ -35,7 +36,7 @@ func TestAccDigitalOceanRecord_Basic(t *testing.T) {
}
func TestAccDigitalOceanRecord_Updated(t *testing.T) {
var record digitalocean.Record
var record godo.DomainRecord
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
@ -77,7 +78,7 @@ func TestAccDigitalOceanRecord_Updated(t *testing.T) {
}
func TestAccDigitalOceanRecord_HostnameValue(t *testing.T) {
var record digitalocean.Record
var record godo.DomainRecord
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
@ -104,7 +105,7 @@ func TestAccDigitalOceanRecord_HostnameValue(t *testing.T) {
}
func TestAccDigitalOceanRecord_RelativeHostnameValue(t *testing.T) {
var record digitalocean.Record
var record godo.DomainRecord
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
@ -131,7 +132,7 @@ func TestAccDigitalOceanRecord_RelativeHostnameValue(t *testing.T) {
}
func TestAccDigitalOceanRecord_ExternalHostnameValue(t *testing.T) {
var record digitalocean.Record
var record godo.DomainRecord
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
@ -158,14 +159,19 @@ func TestAccDigitalOceanRecord_ExternalHostnameValue(t *testing.T) {
}
func testAccCheckDigitalOceanRecordDestroy(s *terraform.State) error {
client := testAccProvider.Meta().(*digitalocean.Client)
client := testAccProvider.Meta().(*godo.Client)
for _, rs := range s.RootModule().Resources {
if rs.Type != "digitalocean_record" {
continue
}
domain := rs.Primary.Attributes["domain"]
id, err := strconv.Atoi(rs.Primary.ID)
if err != nil {
return err
}
_, err := client.RetrieveRecord(rs.Primary.Attributes["domain"], rs.Primary.ID)
_, _, err = client.Domains.Record(domain, id)
if err == nil {
return fmt.Errorf("Record still exists")
@ -175,7 +181,7 @@ func testAccCheckDigitalOceanRecordDestroy(s *terraform.State) error {
return nil
}
func testAccCheckDigitalOceanRecordAttributes(record *digitalocean.Record) resource.TestCheckFunc {
func testAccCheckDigitalOceanRecordAttributes(record *godo.DomainRecord) resource.TestCheckFunc {
return func(s *terraform.State) error {
if record.Data != "192.168.0.10" {
@ -186,7 +192,7 @@ func testAccCheckDigitalOceanRecordAttributes(record *digitalocean.Record) resou
}
}
func testAccCheckDigitalOceanRecordAttributesUpdated(record *digitalocean.Record) resource.TestCheckFunc {
func testAccCheckDigitalOceanRecordAttributesUpdated(record *godo.DomainRecord) resource.TestCheckFunc {
return func(s *terraform.State) error {
if record.Data != "192.168.0.11" {
@ -197,7 +203,7 @@ func testAccCheckDigitalOceanRecordAttributesUpdated(record *digitalocean.Record
}
}
func testAccCheckDigitalOceanRecordExists(n string, record *digitalocean.Record) resource.TestCheckFunc {
func testAccCheckDigitalOceanRecordExists(n string, record *godo.DomainRecord) resource.TestCheckFunc {
return func(s *terraform.State) error {
rs, ok := s.RootModule().Resources[n]
@ -209,25 +215,31 @@ func testAccCheckDigitalOceanRecordExists(n string, record *digitalocean.Record)
return fmt.Errorf("No Record ID is set")
}
client := testAccProvider.Meta().(*digitalocean.Client)
client := testAccProvider.Meta().(*godo.Client)
foundRecord, err := client.RetrieveRecord(rs.Primary.Attributes["domain"], rs.Primary.ID)
domain := rs.Primary.Attributes["domain"]
id, err := strconv.Atoi(rs.Primary.ID)
if err != nil {
return err
}
foundRecord, _, err := client.Domains.Record(domain, id)
if err != nil {
return err
}
if foundRecord.StringId() != rs.Primary.ID {
if strconv.Itoa(foundRecord.ID) != rs.Primary.ID {
return fmt.Errorf("Record not found")
}
*record = foundRecord
*record = *foundRecord
return nil
}
}
func testAccCheckDigitalOceanRecordAttributesHostname(data string, record *digitalocean.Record) resource.TestCheckFunc {
func testAccCheckDigitalOceanRecordAttributesHostname(data string, record *godo.DomainRecord) resource.TestCheckFunc {
return func(s *terraform.State) error {
if record.Data != data {

View File

@ -3,10 +3,11 @@ package digitalocean
import (
"fmt"
"log"
"strconv"
"strings"
"github.com/digitalocean/godo"
"github.com/hashicorp/terraform/helper/schema"
"github.com/pearkes/digitalocean"
)
func resourceDigitalOceanSSHKey() *schema.Resource {
@ -42,30 +43,35 @@ func resourceDigitalOceanSSHKey() *schema.Resource {
}
func resourceDigitalOceanSSHKeyCreate(d *schema.ResourceData, meta interface{}) error {
client := meta.(*digitalocean.Client)
client := meta.(*godo.Client)
// Build up our creation options
opts := &digitalocean.CreateSSHKey{
opts := &godo.KeyCreateRequest{
Name: d.Get("name").(string),
PublicKey: d.Get("public_key").(string),
}
log.Printf("[DEBUG] SSH Key create configuration: %#v", opts)
id, err := client.CreateSSHKey(opts)
key, _, err := client.Keys.Create(opts)
if err != nil {
return fmt.Errorf("Error creating SSH Key: %s", err)
}
d.SetId(id)
log.Printf("[INFO] SSH Key: %s", id)
d.SetId(strconv.Itoa(key.ID))
log.Printf("[INFO] SSH Key: %d", key.ID)
return resourceDigitalOceanSSHKeyRead(d, meta)
}
func resourceDigitalOceanSSHKeyRead(d *schema.ResourceData, meta interface{}) error {
client := meta.(*digitalocean.Client)
client := meta.(*godo.Client)
key, err := client.RetrieveSSHKey(d.Id())
id, err := strconv.Atoi(d.Id())
if err != nil {
return fmt.Errorf("invalid SSH key id: %v", err)
}
key, _, err := client.Keys.GetByID(id)
if err != nil {
// If the key is somehow already destroyed, mark as
// successfully gone
@ -84,7 +90,12 @@ func resourceDigitalOceanSSHKeyRead(d *schema.ResourceData, meta interface{}) er
}
func resourceDigitalOceanSSHKeyUpdate(d *schema.ResourceData, meta interface{}) error {
client := meta.(*digitalocean.Client)
client := meta.(*godo.Client)
id, err := strconv.Atoi(d.Id())
if err != nil {
return fmt.Errorf("invalid SSH key id: %v", err)
}
var newName string
if v, ok := d.GetOk("name"); ok {
@ -92,7 +103,10 @@ func resourceDigitalOceanSSHKeyUpdate(d *schema.ResourceData, meta interface{})
}
log.Printf("[DEBUG] SSH key update name: %#v", newName)
err := client.RenameSSHKey(d.Id(), newName)
opts := &godo.KeyUpdateRequest{
Name: newName,
}
_, _, err = client.Keys.UpdateByID(id, opts)
if err != nil {
return fmt.Errorf("Failed to update SSH key: %s", err)
}
@ -101,10 +115,15 @@ func resourceDigitalOceanSSHKeyUpdate(d *schema.ResourceData, meta interface{})
}
func resourceDigitalOceanSSHKeyDelete(d *schema.ResourceData, meta interface{}) error {
client := meta.(*digitalocean.Client)
client := meta.(*godo.Client)
log.Printf("[INFO] Deleting SSH key: %s", d.Id())
err := client.DestroySSHKey(d.Id())
id, err := strconv.Atoi(d.Id())
if err != nil {
return fmt.Errorf("invalid SSH key id: %v", err)
}
log.Printf("[INFO] Deleting SSH key: %d", id)
_, err = client.Keys.DeleteByID(id)
if err != nil {
return fmt.Errorf("Error deleting SSH key: %s", err)
}

View File

@ -6,13 +6,13 @@ import (
"strings"
"testing"
"github.com/digitalocean/godo"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
"github.com/pearkes/digitalocean"
)
func TestAccDigitalOceanSSHKey_Basic(t *testing.T) {
var key digitalocean.SSHKey
var key godo.Key
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
@ -35,15 +35,20 @@ func TestAccDigitalOceanSSHKey_Basic(t *testing.T) {
}
func testAccCheckDigitalOceanSSHKeyDestroy(s *terraform.State) error {
client := testAccProvider.Meta().(*digitalocean.Client)
client := testAccProvider.Meta().(*godo.Client)
for _, rs := range s.RootModule().Resources {
if rs.Type != "digitalocean_ssh_key" {
continue
}
id, err := strconv.Atoi(rs.Primary.ID)
if err != nil {
return err
}
// Try to find the key
_, err := client.RetrieveSSHKey(rs.Primary.ID)
_, _, err = client.Keys.GetByID(id)
if err == nil {
fmt.Errorf("SSH key still exists")
@ -53,7 +58,7 @@ func testAccCheckDigitalOceanSSHKeyDestroy(s *terraform.State) error {
return nil
}
func testAccCheckDigitalOceanSSHKeyAttributes(key *digitalocean.SSHKey) resource.TestCheckFunc {
func testAccCheckDigitalOceanSSHKeyAttributes(key *godo.Key) resource.TestCheckFunc {
return func(s *terraform.State) error {
if key.Name != "foobar" {
@ -64,7 +69,7 @@ func testAccCheckDigitalOceanSSHKeyAttributes(key *digitalocean.SSHKey) resource
}
}
func testAccCheckDigitalOceanSSHKeyExists(n string, key *digitalocean.SSHKey) resource.TestCheckFunc {
func testAccCheckDigitalOceanSSHKeyExists(n string, key *godo.Key) resource.TestCheckFunc {
return func(s *terraform.State) error {
rs, ok := s.RootModule().Resources[n]
@ -76,19 +81,25 @@ func testAccCheckDigitalOceanSSHKeyExists(n string, key *digitalocean.SSHKey) re
return fmt.Errorf("No Record ID is set")
}
client := testAccProvider.Meta().(*digitalocean.Client)
client := testAccProvider.Meta().(*godo.Client)
foundKey, err := client.RetrieveSSHKey(rs.Primary.ID)
id, err := strconv.Atoi(rs.Primary.ID)
if err != nil {
return err
}
// Try to find the key
foundKey, _, err := client.Keys.GetByID(id)
if err != nil {
return err
}
if strconv.Itoa(int(foundKey.Id)) != rs.Primary.ID {
if strconv.Itoa(foundKey.ID) != rs.Primary.ID {
return fmt.Errorf("Record not found")
}
*key = foundKey
*key = *foundKey
return nil
}