diff --git a/.changelog/9740.txt b/.changelog/9740.txt new file mode 100644 index 00000000000..e3b31b81683 --- /dev/null +++ b/.changelog/9740.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +compute: added update support to `params.resource_manager_tags` in `google_compute_instance` +``` diff --git a/google/services/compute/resource_compute_instance.go b/google/services/compute/resource_compute_instance.go index 050ae0106df..1c60ed5357b 100644 --- a/google/services/compute/resource_compute_instance.go +++ b/google/services/compute/resource_compute_instance.go @@ -232,8 +232,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.`, }, @@ -613,10 +613,8 @@ func ResourceComputeInstance() *schema.Resource { Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "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, + Type: schema.TypeMap, + Optional: 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.`, }, }, @@ -1717,6 +1715,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/google/services/compute/resource_compute_instance_test.go b/google/services/compute/resource_compute_instance_test.go index cfacb1dba85..a349399e8b6 100644 --- a/google/services/compute/resource_compute_instance_test.go +++ b/google/services/compute/resource_compute_instance_test.go @@ -263,6 +263,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)), + }, }, }) } @@ -3572,8 +3578,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 { @@ -3593,9 +3597,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)