From e8966c389f49f0b991c1fbd82b287fa67ad31414 Mon Sep 17 00:00:00 2001 From: Luca Prete Date: Tue, 9 Jan 2024 20:27:38 +0100 Subject: [PATCH] Allow users to update google_compute_instance resource_manager_tags in place (#9740) * Initial commit * Fixes --------- Co-authored-by: Luca Prete --- .../compute/resource_compute_instance.go.erb | 46 +++++++++++-- .../resource_compute_instance_test.go.erb | 69 +++++++++++++++++-- 2 files changed, 103 insertions(+), 12 deletions(-) diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_instance.go.erb b/mmv1/third_party/terraform/services/compute/resource_compute_instance.go.erb index b251845fe061..628894cd7c4f 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_instance.go.erb +++ b/mmv1/third_party/terraform/services/compute/resource_compute_instance.go.erb @@ -242,8 +242,8 @@ func ResourceComputeInstance() *schema.Resource { "resource_manager_tags": { Type: schema.TypeMap, Optional: true, - AtLeastOneOf: initializeParamsKeys, ForceNew: true, + AtLeastOneOf: initializeParamsKeys, Description: `A map of resource manager tags. Resource manager tag keys and values have the same definition as resource manager tags. Keys must be in the format tagKeys/{tag_key_id}, and values are in the format tagValues/456. The field is ignored (both PUT & PATCH) when empty.`, }, @@ -269,11 +269,11 @@ func ResourceComputeInstance() *schema.Resource { <% unless version == 'ga' -%> "enable_confidential_compute": { - Type: schema.TypeBool, - Optional: true, + Type: schema.TypeBool, + Optional: true, AtLeastOneOf: initializeParamsKeys, - ForceNew: true, - Description: `A flag to enable confidential compute mode on boot disk`, + ForceNew: true, + Description: `A flag to enable confidential compute mode on boot disk`, }, <% end -%> }, @@ -668,8 +668,6 @@ func ResourceComputeInstance() *schema.Resource { "resource_manager_tags": { Type: schema.TypeMap, Optional: true, - // This field is intentionally not updatable. The API overrides all existing tags on the field when updated. See go/gce-tags-terraform-support for details. - ForceNew: true, Description: `A map of resource manager tags. Resource manager tag keys and values have the same definition as resource manager tags. Keys must be in the format tagKeys/{tag_key_id}, and values are in the format tagValues/456. The field is ignored (both PUT & PATCH) when empty.`, }, }, @@ -1829,6 +1827,40 @@ func resourceComputeInstanceUpdate(d *schema.ResourceData, meta interface{}) err } } + if d.HasChange("params.0.resource_manager_tags") { + err = transport_tpg.Retry(transport_tpg.RetryOptions{ + RetryFunc: func() error { + instance, err := config.NewComputeClient(userAgent).Instances.Get(project, zone, instance.Name).Do() + if err != nil { + return fmt.Errorf("Error retrieving instance: %s", err) + } + + params, err := expandParams(d) + if err != nil { + return fmt.Errorf("Error updating params: %s", err) + } + + instance.Params = params + + op, err := config.NewComputeClient(userAgent).Instances.Update(project, zone, instance.Name, instance).Do() + if err != nil { + return fmt.Errorf("Error updating instance: %s", err) + } + + opErr := ComputeOperationWaitTime(config, op, project, "resource_manager_tags, updating", userAgent, d.Timeout(schema.TimeoutUpdate)) + if opErr != nil { + return opErr + } + + return nil + }, + }) + + if err != nil { + return err + } + } + if d.HasChange("resource_policies") { if len(instance.ResourcePolicies) > 0 { req := compute.InstancesRemoveResourcePoliciesRequest{ResourcePolicies: instance.ResourcePolicies} diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_instance_test.go.erb b/mmv1/third_party/terraform/services/compute/resource_compute_instance_test.go.erb index 7acfae4faca2..187bd2488b28 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_instance_test.go.erb +++ b/mmv1/third_party/terraform/services/compute/resource_compute_instance_test.go.erb @@ -250,7 +250,7 @@ func TestAccComputeInstance_resourceManagerTags(t *testing.T) { var instance compute.Instance var instanceName = fmt.Sprintf("tf-test-%s", acctest.RandString(t, 10)) context := map[string]interface{}{ - "project": envvar.GetTestProjectFromEnv(), + "project": envvar.GetTestProjectFromEnv(), "random_suffix": acctest.RandString(t, 10), "instance_name": instanceName, } @@ -266,6 +266,12 @@ func TestAccComputeInstance_resourceManagerTags(t *testing.T) { testAccCheckComputeInstanceExists( t, "google_compute_instance.foobar", &instance)), }, + { + Config: testAccComputeInstance_resourceManagerTagsUpdate(context), + Check: resource.ComposeTestCheckFunc( + testAccCheckComputeInstanceExists( + t, "google_compute_instance.foobar", &instance)), + }, }, }) } @@ -4160,8 +4166,6 @@ resource "google_compute_instance" "foobar" { name = "%{instance_name}" machine_type = "e2-medium" zone = "us-central1-a" - can_ip_forward = false - tags = ["tag-key", "tag-value"] boot_disk { initialize_params { @@ -4181,9 +4185,64 @@ resource "google_compute_instance" "foobar" { network_interface { network = "default" } +} +`, context) +} - metadata = { - foo = "bar" +func testAccComputeInstance_resourceManagerTagsUpdate(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_tags_tag_key" "key" { + parent = "projects/%{project}" + short_name = "foobarbaz%{random_suffix}" + description = "For foo/bar resources." +} + +resource "google_tags_tag_value" "value" { + parent = "tagKeys/${google_tags_tag_key.key.name}" + short_name = "foo%{random_suffix}" + description = "For foo resources." +} + +resource "google_tags_tag_key" "key_new" { + parent = "projects/%{project}" + short_name = "foobarbaznew%{random_suffix}" + description = "New key for foo/bar resources." +} + +resource "google_tags_tag_value" "value_new" { + parent = "tagKeys/${google_tags_tag_key.key_new.name}" + short_name = "foonew%{random_suffix}" + description = "New value for foo resources." +} + +data "google_compute_image" "my_image" { + family = "debian-11" + project = "debian-cloud" +} + +resource "google_compute_instance" "foobar" { + name = "%{instance_name}" + machine_type = "e2-medium" + zone = "us-central1-a" + + boot_disk { + initialize_params { + image = data.google_compute_image.my_image.self_link + resource_manager_tags = { + "tagKeys/${google_tags_tag_key.key.name}" = "tagValues/${google_tags_tag_value.value.name}" + } + } + } + + params { + resource_manager_tags = { + "tagKeys/${google_tags_tag_key.key.name}" = "tagValues/${google_tags_tag_value.value.name}" + "tagKeys/${google_tags_tag_key.key_new.name}" = "tagValues/${google_tags_tag_value.value_new.name}" + } + } + + network_interface { + network = "default" } } `, context)