From 0965332b88293a38ec7d34d053e942714e3e569b Mon Sep 17 00:00:00 2001 From: Jack Pearkes Date: Sat, 19 Jul 2014 09:45:42 -0400 Subject: [PATCH] providers/digitalocean: WaitForAttribute --- .../resource_digitalocean_droplet.go | 73 ++++++++++++------- .../resource_digitalocean_droplet_test.go | 24 +++--- 2 files changed, 61 insertions(+), 36 deletions(-) diff --git a/builtin/providers/digitalocean/resource_digitalocean_droplet.go b/builtin/providers/digitalocean/resource_digitalocean_droplet.go index 9f8eba46b..562fc151c 100644 --- a/builtin/providers/digitalocean/resource_digitalocean_droplet.go +++ b/builtin/providers/digitalocean/resource_digitalocean_droplet.go @@ -71,20 +71,7 @@ func resource_digitalocean_droplet_create( log.Printf("[INFO] Droplet ID: %s", id) - // Wait for the droplet so we can get the networking attributes - // that show up after a while - log.Printf( - "[DEBUG] Waiting for Droplet (%s) to become running", - id) - - stateConf := &resource.StateChangeConf{ - Pending: []string{"new"}, - Target: "active", - Refresh: DropletStateRefreshFunc(client, id), - Timeout: 10 * time.Minute, - } - - dropletRaw, err := stateConf.WaitForState() + dropletRaw, err := WaitForDropletAttribute(id, "active", []string{"new"}, "status", client) if err != nil { return rs, fmt.Errorf( @@ -101,8 +88,15 @@ func resource_digitalocean_droplet_update( s *terraform.ResourceState, d *terraform.ResourceDiff, meta interface{}) (*terraform.ResourceState, error) { + // p := meta.(*ResourceProvider) + // client := p.client + // rs := s.MergeDiff(d) - panic("No update") + // var err error + + // if _, ok := d.Attributes["size"]; ok { + + // } return nil, nil } @@ -222,23 +216,48 @@ func resource_digitalocean_droplet_validation() *config.Validator { } } -// DropletStateRefreshFunc returns a resource.StateRefreshFunc that is used to watch -// a droplet. -func DropletStateRefreshFunc(client *digitalocean.Client, id string) resource.StateRefreshFunc { - return func() (interface{}, string, error) { - droplet, err := resource_digitalocean_droplet_retrieve(id, client) +func WaitForDropletAttribute(id string, target string, pending []string, attribute string, client *digitalocean.Client) (interface{}, error) { + // Wait for the droplet so we can get the networking attributes + // that show up after a while + log.Printf( + "[DEBUG] Waiting for Droplet (%s) to have %s of %s", + id, attribute, target) - // It's not actually "active" - // until we can see the image slug - if droplet.ImageSlug() == "" { - return nil, "", nil - } + stateConf := &resource.StateChangeConf{ + Pending: pending, + Target: target, + Refresh: new_droplet_state_refresh_func(id, attribute, client), + Timeout: 10 * time.Minute, + } + + return stateConf.WaitForState() +} + +func new_droplet_state_refresh_func(id string, attribute string, client *digitalocean.Client) resource.StateRefreshFunc { + return func() (interface{}, string, error) { + // Retrieve the ELB properties for updating the state + droplet, err := client.RetrieveDroplet(id) if err != nil { - log.Printf("Error on DropletStateRefresh: %s", err) + log.Printf("Error on retrieving droplet when waiting: %s", err) return nil, "", err } - return droplet, droplet.Status, nil + // Use our mapping to get back a map of the + // droplet properties + resourceMap, err := resource_digitalocean_droplet_update_state( + &terraform.ResourceState{Attributes: map[string]string{}}, &droplet) + + if err != nil { + log.Printf("Error creating map from droplet: %s", err) + return nil, "", err + } + + // See if we can access our attribute + if attr, ok := resourceMap.Attributes[attribute]; ok { + return &droplet, attr, nil + } + + return nil, "", nil } } diff --git a/builtin/providers/digitalocean/resource_digitalocean_droplet_test.go b/builtin/providers/digitalocean/resource_digitalocean_droplet_test.go index b66484745..69c378d4c 100644 --- a/builtin/providers/digitalocean/resource_digitalocean_droplet_test.go +++ b/builtin/providers/digitalocean/resource_digitalocean_droplet_test.go @@ -4,7 +4,6 @@ import ( "fmt" "strings" "testing" - "time" "github.com/hashicorp/terraform/helper/resource" "github.com/hashicorp/terraform/terraform" @@ -49,14 +48,7 @@ func testAccCheckDigitalOceanDropletDestroy(s *terraform.State) error { // Try to find the Droplet _, err := client.RetrieveDroplet(rs.ID) - stateConf := &resource.StateChangeConf{ - Pending: []string{"new"}, - Target: "off", - Refresh: DropletStateRefreshFunc(client, rs.ID), - Timeout: 10 * time.Minute, - } - - _, err = stateConf.WaitForState() + // Wait if err != nil && !strings.Contains(err.Error(), "404") { return fmt.Errorf( @@ -120,6 +112,20 @@ func testAccCheckDigitalOceanDropletExists(n string, droplet *digitalocean.Dropl } } +func Test_new_droplet_state_refresh_func(t *testing.T) { + droplet := digitalocean.Droplet{ + Name: "foobar", + } + resourceMap, _ := resource_digitalocean_droplet_update_state( + &terraform.ResourceState{Attributes: map[string]string{}}, &droplet) + + // See if we can access our attribute + if _, ok := resourceMap.Attributes["name"]; !ok { + t.Fatalf("bad name: %s", resourceMap.Attributes) + } + +} + const testAccCheckDigitalOceanDropletConfig_basic = ` resource "digitalocean_droplet" "foobar" { name = "foo"