diff --git a/CHANGELOG.md b/CHANGELOG.md index 11ea73baae9..b29e72fa061 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,7 +9,6 @@ FEATURES: * **New Resource:** `google_bigtable_instance` [GH-177] * **New Resource:** `google_bigtable_table` [GH-177] -* **New Resource:** `google_compute_project_metadata_item` - allows management of single key/value pairs within the project metadata map [GH-176] IMPROVEMENTS: diff --git a/google/import_compute_project_metadata_item_test.go b/google/import_compute_project_metadata_item_test.go deleted file mode 100644 index 8b0089b8fc9..00000000000 --- a/google/import_compute_project_metadata_item_test.go +++ /dev/null @@ -1,25 +0,0 @@ -package google - -import ( - "testing" - - "github.com/hashicorp/terraform/helper/resource" -) - -func TestAccComputeProjectMetadataItem_importBasic(t *testing.T) { - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, - CheckDestroy: testAccCheckProjectMetadataItemDestroy, - Steps: []resource.TestStep{ - { - Config: testAccProjectMetadataItem_basic("myKey", "myValue"), - }, - { - ResourceName: "google_compute_project_metadata_item.foobar", - ImportState: true, - ImportStateVerify: true, - }, - }, - }) -} diff --git a/google/metadata.go b/google/metadata.go index 230b7a169ec..e2ebd18a3d1 100644 --- a/google/metadata.go +++ b/google/metadata.go @@ -2,15 +2,12 @@ package google import ( "fmt" - "log" - "strings" "google.golang.org/api/compute/v1" ) const FINGERPRINT_RETRIES = 10 - -var FINGERPRINT_FAIL_ERRORS = []string{"Invalid fingerprint.", "Supplied fingerprint does not match current metadata fingerprint."} +const FINGERPRINT_FAIL = "Invalid fingerprint." // Since the google compute API uses optimistic locking, there is a chance // we need to resubmit our updated metadata. To do this, you need to provide @@ -19,25 +16,11 @@ func MetadataRetryWrapper(update func() error) error { attempt := 0 for attempt < FINGERPRINT_RETRIES { err := update() - if err == nil { - return nil - } - - // Check to see if the error matches any of our fingerprint-related failure messages - var fingerprintError bool - for _, msg := range FINGERPRINT_FAIL_ERRORS { - if strings.Contains(err.Error(), msg) { - fingerprintError = true - break - } - } - - if !fingerprintError { - // Something else went wrong, don't retry + if err != nil && err.Error() == FINGERPRINT_FAIL { + attempt++ + } else { return err } - - attempt++ } return fmt.Errorf("Failed to update metadata after %d retries", attempt) @@ -88,43 +71,3 @@ func MetadataFormatSchema(curMDMap map[string]interface{}, md *compute.Metadata) return newMD } - -// flattenComputeMetadata transforms a list of MetadataItems (as returned via the GCP client) into a simple map from key -// to value. -func flattenComputeMetadata(metadata []*compute.MetadataItems) map[string]string { - m := map[string]string{} - - for _, item := range metadata { - // check for duplicates - if item.Value == nil { - continue - } - if val, ok := m[item.Key]; ok { - // warn loudly! - log.Printf("[WARN] Key '%s' already has value '%s' when flattening - ignoring incoming value '%s'", - item.Key, - val, - *item.Value) - } - m[item.Key] = *item.Value - } - - return m -} - -// expandComputeMetadata transforms a map representing computing metadata into a list of compute.MetadataItems suitable -// for the GCP client. -func expandComputeMetadata(m map[string]string) []*compute.MetadataItems { - metadata := make([]*compute.MetadataItems, len(m)) - - idx := 0 - for key, value := range m { - // Make a copy of value as we need a ptr type; if we directly use 'value' then all items will reference the same - // memory address - vtmp := value - metadata[idx] = &compute.MetadataItems{Key: key, Value: &vtmp} - idx++ - } - - return metadata -} diff --git a/google/provider.go b/google/provider.go index bda33019ab9..5bff44c89b9 100644 --- a/google/provider.go +++ b/google/provider.go @@ -86,7 +86,6 @@ func Provider() terraform.ResourceProvider { "google_compute_instance_template": resourceComputeInstanceTemplate(), "google_compute_network": resourceComputeNetwork(), "google_compute_project_metadata": resourceComputeProjectMetadata(), - "google_compute_project_metadata_item": resourceComputeProjectMetadataItem(), "google_compute_region_backend_service": resourceComputeRegionBackendService(), "google_compute_route": resourceComputeRoute(), "google_compute_router": resourceComputeRouter(), diff --git a/google/resource_compute_project_metadata_item.go b/google/resource_compute_project_metadata_item.go deleted file mode 100644 index dc017d32a13..00000000000 --- a/google/resource_compute_project_metadata_item.go +++ /dev/null @@ -1,178 +0,0 @@ -package google - -import ( - "fmt" - "log" - - "github.com/hashicorp/terraform/helper/schema" - "google.golang.org/api/compute/v1" -) - -func resourceComputeProjectMetadataItem() *schema.Resource { - return &schema.Resource{ - Create: resourceComputeProjectMetadataItemCreate, - Read: resourceComputeProjectMetadataItemRead, - Update: resourceComputeProjectMetadataItemUpdate, - Delete: resourceComputeProjectMetadataItemDelete, - Importer: &schema.ResourceImporter{ - State: schema.ImportStatePassthrough, - }, - - Schema: map[string]*schema.Schema{ - "key": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - }, - "value": { - Type: schema.TypeString, - Required: true, - }, - "project": { - Type: schema.TypeString, - Optional: true, - ForceNew: true, - }, - }, - } -} - -func resourceComputeProjectMetadataItemCreate(d *schema.ResourceData, meta interface{}) error { - config := meta.(*Config) - - projectID, err := getProject(d, config) - if err != nil { - return err - } - - key := d.Get("key").(string) - val := d.Get("value").(string) - - err = updateComputeCommonInstanceMetadata(config, projectID, key, &val) - if err != nil { - return err - } - - d.SetId(key) - - return nil -} - -func resourceComputeProjectMetadataItemRead(d *schema.ResourceData, meta interface{}) error { - config := meta.(*Config) - - projectID, err := getProject(d, config) - if err != nil { - return err - } - - log.Printf("[DEBUG] Loading project metadata: %s", projectID) - project, err := config.clientCompute.Projects.Get(projectID).Do() - if err != nil { - return fmt.Errorf("Error loading project '%s': %s", projectID, err) - } - - md := flattenComputeMetadata(project.CommonInstanceMetadata.Items) - val, ok := md[d.Id()] - if !ok { - // Resource no longer exists - d.SetId("") - return nil - } - - d.Set("key", d.Id()) - d.Set("value", val) - - return nil -} - -func resourceComputeProjectMetadataItemUpdate(d *schema.ResourceData, meta interface{}) error { - config := meta.(*Config) - - projectID, err := getProject(d, config) - if err != nil { - return err - } - - if d.HasChange("value") { - key := d.Get("key").(string) - _, n := d.GetChange("value") - new := n.(string) - - err = updateComputeCommonInstanceMetadata(config, projectID, key, &new) - if err != nil { - return err - } - } - return nil -} - -func resourceComputeProjectMetadataItemDelete(d *schema.ResourceData, meta interface{}) error { - config := meta.(*Config) - - projectID, err := getProject(d, config) - if err != nil { - return err - } - - key := d.Get("key").(string) - - err = updateComputeCommonInstanceMetadata(config, projectID, key, nil) - if err != nil { - return err - } - - d.SetId("") - return nil -} - -func updateComputeCommonInstanceMetadata(config *Config, projectID string, key string, afterVal *string) error { - updateMD := func() error { - log.Printf("[DEBUG] Loading project metadata: %s", projectID) - project, err := config.clientCompute.Projects.Get(projectID).Do() - if err != nil { - return fmt.Errorf("Error loading project '%s': %s", projectID, err) - } - - md := flattenComputeMetadata(project.CommonInstanceMetadata.Items) - - val, ok := md[key] - - if !ok { - if afterVal == nil { - // Asked to set no value and we didn't find one - we're done - return nil - } - } else { - if afterVal != nil && *afterVal == val { - // Asked to set a value and it's already set - we're done. - return nil - } - } - - if afterVal == nil { - delete(md, key) - } else { - md[key] = *afterVal - } - - // Attempt to write the new value now - op, err := config.clientCompute.Projects.SetCommonInstanceMetadata( - projectID, - &compute.Metadata{ - Fingerprint: project.CommonInstanceMetadata.Fingerprint, - Items: expandComputeMetadata(md), - }, - ).Do() - - if err != nil { - return err - } - - log.Printf("[DEBUG] SetCommonInstanceMetadata: %d (%s)", op.Id, op.SelfLink) - - return computeOperationWaitGlobal(config, op, project.Name, "SetCommonInstanceMetadata") - } - - return MetadataRetryWrapper(updateMD) -} diff --git a/google/resource_compute_project_metadata_item_test.go b/google/resource_compute_project_metadata_item_test.go deleted file mode 100644 index 695ab2e1cf8..00000000000 --- a/google/resource_compute_project_metadata_item_test.go +++ /dev/null @@ -1,118 +0,0 @@ -package google - -import ( - "fmt" - "testing" - - "github.com/hashicorp/terraform/helper/resource" - "github.com/hashicorp/terraform/terraform" -) - -func TestAccComputeProjectMetadataItem_basic(t *testing.T) { - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, - CheckDestroy: testAccCheckProjectMetadataItemDestroy, - Steps: []resource.TestStep{ - { - Config: testAccProjectMetadataItem_basic("myKey", "myValue"), - Check: resource.ComposeTestCheckFunc( - testAccCheckProjectMetadataItem_hasMetadata("myKey", "myValue"), - ), - }, - }, - }) -} - -func TestAccComputeProjectMetadataItem_basicWithEmptyVal(t *testing.T) { - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, - CheckDestroy: testAccCheckProjectMetadataItemDestroy, - Steps: []resource.TestStep{ - { - Config: testAccProjectMetadataItem_basic("myKey", ""), - Check: resource.ComposeTestCheckFunc( - testAccCheckProjectMetadataItem_hasMetadata("myKey", ""), - ), - }, - }, - }) -} - -func TestAccComputeProjectMetadataItem_basicUpdate(t *testing.T) { - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, - CheckDestroy: testAccCheckProjectMetadataItemDestroy, - Steps: []resource.TestStep{ - { - Config: testAccProjectMetadataItem_basic("myKey", "myValue"), - Check: resource.ComposeTestCheckFunc( - testAccCheckProjectMetadataItem_hasMetadata("myKey", "myValue"), - ), - }, - { - Config: testAccProjectMetadataItem_basic("myKey", "myUpdatedValue"), - Check: resource.ComposeTestCheckFunc( - testAccCheckProjectMetadataItem_hasMetadata("myKey", "myUpdatedValue"), - ), - }, - }, - }) -} - -func testAccCheckProjectMetadataItem_hasMetadata(key, value string) resource.TestCheckFunc { - return func(s *terraform.State) error { - config := testAccProvider.Meta().(*Config) - - project, err := config.clientCompute.Projects.Get(config.Project).Do() - if err != nil { - return err - } - - metadata := flattenComputeMetadata(project.CommonInstanceMetadata.Items) - - val, ok := metadata[key] - if !ok { - return fmt.Errorf("Unable to find a value for key '%s'", key) - } - if val != value { - return fmt.Errorf("Value for key '%s' does not match. Expected '%s' but found '%s'", key, value, val) - } - return nil - } -} - -func testAccCheckProjectMetadataItemDestroy(s *terraform.State) error { - config := testAccProvider.Meta().(*Config) - - project, err := config.clientCompute.Projects.Get(config.Project).Do() - if err != nil { - return err - } - - metadata := flattenComputeMetadata(project.CommonInstanceMetadata.Items) - - for _, rs := range s.RootModule().Resources { - if rs.Type != "google_compute_project_metadata_item" { - continue - } - - _, ok := metadata[rs.Primary.ID] - if ok { - return fmt.Errorf("Metadata key/value '%s': '%s' still exist", rs.Primary.Attributes["key"], rs.Primary.Attributes["value"]) - } - } - - return nil -} - -func testAccProjectMetadataItem_basic(key, val string) string { - return fmt.Sprintf(` -resource "google_compute_project_metadata_item" "foobar" { - key = "%s" - value = "%s" -} -`, key, val) -} diff --git a/website/docs/r/compute_project_metadata.html.markdown b/website/docs/r/compute_project_metadata.html.markdown index c240fb7ca08..3b7dd19df18 100644 --- a/website/docs/r/compute_project_metadata.html.markdown +++ b/website/docs/r/compute_project_metadata.html.markdown @@ -8,10 +8,7 @@ description: |- # google\_compute\_project\_metadata -Manages metadata common to all instances for a project in GCE. If you -want to manage only single key/value pairs within the project metadata -rather than the entire set, then use -[google_compute_project_metadata_item](compute_project_metadata_item.html). +Manages metadata common to all instances for a project in GCE. ## Example Usage diff --git a/website/docs/r/compute_project_metadata_item.html.markdown b/website/docs/r/compute_project_metadata_item.html.markdown deleted file mode 100644 index a48dd7e247b..00000000000 --- a/website/docs/r/compute_project_metadata_item.html.markdown +++ /dev/null @@ -1,48 +0,0 @@ ---- -layout: "google" -page_title: "Google: google_compute_project_metadata_item" -sidebar_current: "docs-google-compute-project-metadata-item" -description: |- - Manages a single key/value pair on common instance metadata ---- - -# google\_compute\_project\_metadata\_item - -Manages a single key/value pair on metadata common to all instances for -a project in GCE. Using `google_compute_project_metadata_item` lets you -manage a single key/value setting in Terraform rather than the entire -project metadata map. - -## Example Usage - -```hcl -resource "google_compute_project_metadata_item" "default" { - key = "my_metadata" - value = "my_value" -} -``` - -## Argument Reference - -The following arguments are supported: - -* `key` - (Required) The metadata key to set. - -* `value` - (Required) The value to set for the given metadata key. - -- - - - -* `project` - (Optional) The project in which the resource belongs. If it - is not provided, the provider project is used. - -## Attributes Reference - -Only the arguments listed above are exposed as attributes. - -## Import - -Project metadata items can be imported using the `key`, e.g. - -``` -$ terraform import google_compute_project_metadata_item.default my_metadata -``` diff --git a/website/google.erb b/website/google.erb index 2375c65f5e8..42ad6aee1a4 100644 --- a/website/google.erb +++ b/website/google.erb @@ -153,10 +153,6 @@ google_compute_project_metadata - > - google_compute_project_metadata_item - - > google_compute_region_backend_service