From 0bcf557198a2d3997626d7f0cfd7f6bb6d57cf99 Mon Sep 17 00:00:00 2001 From: Antoine Grondin Date: Sun, 27 Sep 2015 00:06:51 -0400 Subject: [PATCH] use official Go client for DigitalOcean provider --- builtin/providers/digitalocean/config.go | 15 +- .../resource_digitalocean_domain.go | 21 +-- .../resource_digitalocean_domain_test.go | 20 +-- .../resource_digitalocean_droplet.go | 138 ++++++++++++------ .../resource_digitalocean_droplet_test.go | 84 ++++++----- .../resource_digitalocean_record.go | 86 +++++++---- .../resource_digitalocean_record_test.go | 44 ++++-- .../resource_digitalocean_ssh_key.go | 45 ++++-- .../resource_digitalocean_ssh_key_test.go | 31 ++-- 9 files changed, 311 insertions(+), 173 deletions(-) diff --git a/builtin/providers/digitalocean/config.go b/builtin/providers/digitalocean/config.go index c9a43bc09..498bf790b 100644 --- a/builtin/providers/digitalocean/config.go +++ b/builtin/providers/digitalocean/config.go @@ -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 } diff --git a/builtin/providers/digitalocean/resource_digitalocean_domain.go b/builtin/providers/digitalocean/resource_digitalocean_domain.go index 8ab5f1884..d7c4edca1 100644 --- a/builtin/providers/digitalocean/resource_digitalocean_domain.go +++ b/builtin/providers/digitalocean/resource_digitalocean_domain.go @@ -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) } diff --git a/builtin/providers/digitalocean/resource_digitalocean_domain_test.go b/builtin/providers/digitalocean/resource_digitalocean_domain_test.go index 918eea155..2801414ee 100644 --- a/builtin/providers/digitalocean/resource_digitalocean_domain_test.go +++ b/builtin/providers/digitalocean/resource_digitalocean_domain_test.go @@ -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 } diff --git a/builtin/providers/digitalocean/resource_digitalocean_droplet.go b/builtin/providers/digitalocean/resource_digitalocean_droplet.go index 88c0c6d07..eb4a195ea 100644 --- a/builtin/providers/digitalocean/resource_digitalocean_droplet.go +++ b/builtin/providers/digitalocean/resource_digitalocean_droplet.go @@ -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 { @@ -101,11 +102,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), @@ -116,7 +119,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 { @@ -128,25 +131,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()) @@ -160,10 +170,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" { @@ -174,48 +189,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) @@ -229,7 +266,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 { @@ -254,7 +291,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( @@ -272,7 +309,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( @@ -292,7 +329,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( @@ -309,7 +346,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( @@ -330,9 +367,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 { @@ -343,7 +385,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") { @@ -386,9 +428,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 } @@ -404,7 +451,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) } @@ -418,8 +465,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 } diff --git a/builtin/providers/digitalocean/resource_digitalocean_droplet_test.go b/builtin/providers/digitalocean/resource_digitalocean_droplet_test.go index 587612e01..730718c3f 100644 --- a/builtin/providers/digitalocean/resource_digitalocean_droplet_test.go +++ b/builtin/providers/digitalocean/resource_digitalocean_droplet_test.go @@ -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( diff --git a/builtin/providers/digitalocean/resource_digitalocean_record.go b/builtin/providers/digitalocean/resource_digitalocean_record.go index 2ff095aae..ebcb2e0f8 100644 --- a/builtin/providers/digitalocean/resource_digitalocean_record.go +++ b/builtin/providers/digitalocean/resource_digitalocean_record.go @@ -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 diff --git a/builtin/providers/digitalocean/resource_digitalocean_record_test.go b/builtin/providers/digitalocean/resource_digitalocean_record_test.go index 139fd30b7..7811ee9c8 100644 --- a/builtin/providers/digitalocean/resource_digitalocean_record_test.go +++ b/builtin/providers/digitalocean/resource_digitalocean_record_test.go @@ -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 { diff --git a/builtin/providers/digitalocean/resource_digitalocean_ssh_key.go b/builtin/providers/digitalocean/resource_digitalocean_ssh_key.go index 96a4ad80d..d6eb96f09 100644 --- a/builtin/providers/digitalocean/resource_digitalocean_ssh_key.go +++ b/builtin/providers/digitalocean/resource_digitalocean_ssh_key.go @@ -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) } diff --git a/builtin/providers/digitalocean/resource_digitalocean_ssh_key_test.go b/builtin/providers/digitalocean/resource_digitalocean_ssh_key_test.go index 009366e18..3aebe1821 100644 --- a/builtin/providers/digitalocean/resource_digitalocean_ssh_key_test.go +++ b/builtin/providers/digitalocean/resource_digitalocean_ssh_key_test.go @@ -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 }