From a451be0140d5aa376fdc600a0b057053ef22f880 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Tue, 26 Aug 2014 13:48:49 -0700 Subject: [PATCH] providers/google: compute_instance supports updating metadata --- .../google/resource_compute_instance.go | 92 +++++++++++++++---- .../google/resource_compute_instance_test.go | 48 ++++++++++ 2 files changed, 122 insertions(+), 18 deletions(-) diff --git a/builtin/providers/google/resource_compute_instance.go b/builtin/providers/google/resource_compute_instance.go index efc627f8d..90d08e9b3 100644 --- a/builtin/providers/google/resource_compute_instance.go +++ b/builtin/providers/google/resource_compute_instance.go @@ -15,6 +15,7 @@ func resourceComputeInstance() *schema.Resource { return &schema.Resource{ Create: resourceComputeInstanceCreate, Read: resourceComputeInstanceRead, + Update: resourceComputeInstanceUpdate, Delete: resourceComputeInstanceDelete, Schema: map[string]*schema.Schema{ @@ -108,6 +109,11 @@ func resourceComputeInstance() *schema.Resource { return hashcode.String(v.(string)) }, }, + + "metadata_fingerprint": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + }, }, } } @@ -210,23 +216,6 @@ func resourceComputeInstanceCreate(d *schema.ResourceData, meta interface{}) err networks = append(networks, &iface) } - // Calculate the metadata - var metadata *compute.Metadata - if v := d.Get("metadata").([]interface{}); len(v) > 0 { - m := new(compute.Metadata) - m.Items = make([]*compute.MetadataItems, 0, len(v)) - for _, v := range v { - for k, v := range v.(map[string]interface{}) { - m.Items = append(m.Items, &compute.MetadataItems{ - Key: k, - Value: v.(string), - }) - } - } - - metadata = m - } - // Calculate the tags var tags *compute.Tags if v := d.Get("tags"); v != nil { @@ -243,7 +232,7 @@ func resourceComputeInstanceCreate(d *schema.ResourceData, meta interface{}) err Description: d.Get("description").(string), Disks: disks, MachineType: machineType.SelfLink, - Metadata: metadata, + Metadata: resourceInstanceMetadata(d), Name: d.Get("name").(string), NetworkInterfaces: networks, Tags: tags, @@ -322,9 +311,52 @@ func resourceComputeInstanceRead(d *schema.ResourceData, meta interface{}) error d.Set(prefix+".internal_address", iface.NetworkIP) } + // Set the metadata fingerprint if there is one. + if instance.Metadata != nil { + d.Set("metadata_fingerprint", instance.Metadata.Fingerprint) + } + return nil } +func resourceComputeInstanceUpdate(d *schema.ResourceData, meta interface{}) error { + config := meta.(*Config) + + // If the Metadata has changed, then update that. + if d.HasChange("metadata") { + metadata := resourceInstanceMetadata(d) + op, err := config.clientCompute.Instances.SetMetadata( + config.Project, d.Get("zone").(string), d.Id(), metadata).Do() + if err != nil { + return fmt.Errorf("Error updating metadata: %s", err) + } + + w := &OperationWaiter{ + Service: config.clientCompute, + Op: op, + Project: config.Project, + Zone: d.Get("zone").(string), + Type: OperationWaitZone, + } + state := w.Conf() + state.Delay = 1 * time.Second + state.Timeout = 5 * time.Minute + state.MinTimeout = 2 * time.Second + opRaw, err := state.WaitForState() + if err != nil { + return fmt.Errorf("Error waiting for metadata to update: %s", err) + } + op = opRaw.(*compute.Operation) + if op.Error != nil { + // Return the error + return OperationError(*op.Error) + } + + } + + return resourceComputeInstanceRead(d, meta) +} + func resourceComputeInstanceDelete(d *schema.ResourceData, meta interface{}) error { config := meta.(*Config) @@ -359,3 +391,27 @@ func resourceComputeInstanceDelete(d *schema.ResourceData, meta interface{}) err d.SetId("") return nil } + +func resourceInstanceMetadata(d *schema.ResourceData) *compute.Metadata { + var metadata *compute.Metadata + if v := d.Get("metadata").([]interface{}); len(v) > 0 { + m := new(compute.Metadata) + m.Items = make([]*compute.MetadataItems, 0, len(v)) + for _, v := range v { + for k, v := range v.(map[string]interface{}) { + m.Items = append(m.Items, &compute.MetadataItems{ + Key: k, + Value: v.(string), + }) + } + } + + // Set the fingerprint. If the metadata has never been set before + // then this will just be blank. + m.Fingerprint = d.Get("metadata_fingerprint").(string) + + metadata = m + } + + return metadata +} diff --git a/builtin/providers/google/resource_compute_instance_test.go b/builtin/providers/google/resource_compute_instance_test.go index a7fe58800..11bab47c3 100644 --- a/builtin/providers/google/resource_compute_instance_test.go +++ b/builtin/providers/google/resource_compute_instance_test.go @@ -50,6 +50,34 @@ func TestAccComputeInstance_IP(t *testing.T) { }) } +func TestAccComputeInstance_update(t *testing.T) { + var instance compute.Instance + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckComputeInstanceDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccComputeInstance_basic, + Check: resource.ComposeTestCheckFunc( + testAccCheckComputeInstanceExists( + "google_compute_instance.foobar", &instance), + ), + }, + resource.TestStep{ + Config: testAccComputeInstance_update, + Check: resource.ComposeTestCheckFunc( + testAccCheckComputeInstanceExists( + "google_compute_instance.foobar", &instance), + testAccCheckComputeInstanceMetadata( + &instance, "bar", "baz"), + ), + }, + }, + }) +} + func testAccCheckComputeInstanceDestroy(s *terraform.State) error { config := testAccProvider.Meta().(*Config) @@ -171,6 +199,26 @@ resource "google_compute_instance" "foobar" { } }` +const testAccComputeInstance_update = ` +resource "google_compute_instance" "foobar" { + name = "terraform-test" + machine_type = "n1-standard-1" + zone = "us-central1-a" + tags = ["foo", "bar"] + + disk { + image = "debian-7-wheezy-v20140814" + } + + network { + source = "default" + } + + metadata { + bar = "baz" + } +}` + const testAccComputeInstance_ip = ` resource "google_compute_address" "foo" { name = "foo"