diff --git a/.changelog/12082.txt b/.changelog/12082.txt new file mode 100644 index 00000000000..70708e7e2f2 --- /dev/null +++ b/.changelog/12082.txt @@ -0,0 +1,6 @@ +```release-note:enhancement +netapp: promoted `zone` and `replica_zone` fields to GA in `google_netapp_storage_pool` resource +``` +```release-note:enhancement +netapp: promoted `zone` and `replica_zone` fields to GA in `google_netapp_volume` resource +``` \ No newline at end of file diff --git a/google/services/netapp/resource_netapp_storage_pool.go b/google/services/netapp/resource_netapp_storage_pool.go index 6e6997cb617..d64ff99fcdc 100644 --- a/google/services/netapp/resource_netapp_storage_pool.go +++ b/google/services/netapp/resource_netapp_storage_pool.go @@ -128,6 +128,19 @@ Please refer to the field 'effective_labels' for all of the labels present on th ForceNew: true, Description: `When enabled, the volumes uses Active Directory as LDAP name service for UID/GID lookups. Required to enable extended group support for NFSv3, using security identifiers for NFSv4.1 or principal names for kerberized NFSv4.1.`, + }, + "replica_zone": { + Type: schema.TypeString, + Optional: true, + Description: `Specifies the replica zone for regional Flex pools. 'zone' and 'replica_zone' values can be swapped to initiate a +[zone switch](https://cloud.google.com/netapp/volumes/docs/configure-and-use/storage-pools/edit-or-delete-storage-pool#switch_active_and_replica_zones).`, + }, + "zone": { + Type: schema.TypeString, + Optional: true, + Description: `Specifies the active zone for regional Flex pools. 'zone' and 'replica_zone' values can be swapped to initiate a +[zone switch](https://cloud.google.com/netapp/volumes/docs/configure-and-use/storage-pools/edit-or-delete-storage-pool#switch_active_and_replica_zones). +If you want to create a zonal Flex pool, specify a zone name for 'location' and omit 'zone'.`, }, "effective_labels": { Type: schema.TypeMap, @@ -218,6 +231,18 @@ func resourceNetappStoragePoolCreate(d *schema.ResourceData, meta interface{}) e } else if v, ok := d.GetOkExists("ldap_enabled"); !tpgresource.IsEmptyValue(reflect.ValueOf(ldapEnabledProp)) && (ok || !reflect.DeepEqual(v, ldapEnabledProp)) { obj["ldapEnabled"] = ldapEnabledProp } + zoneProp, err := expandNetappStoragePoolZone(d.Get("zone"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("zone"); !tpgresource.IsEmptyValue(reflect.ValueOf(zoneProp)) && (ok || !reflect.DeepEqual(v, zoneProp)) { + obj["zone"] = zoneProp + } + replicaZoneProp, err := expandNetappStoragePoolReplicaZone(d.Get("replica_zone"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("replica_zone"); !tpgresource.IsEmptyValue(reflect.ValueOf(replicaZoneProp)) && (ok || !reflect.DeepEqual(v, replicaZoneProp)) { + obj["replicaZone"] = replicaZoneProp + } allowAutoTieringProp, err := expandNetappStoragePoolAllowAutoTiering(d.Get("allow_auto_tiering"), d, config) if err != nil { return err @@ -362,6 +387,12 @@ func resourceNetappStoragePoolRead(d *schema.ResourceData, meta interface{}) err if err := d.Set("encryption_type", flattenNetappStoragePoolEncryptionType(res["encryptionType"], d, config)); err != nil { return fmt.Errorf("Error reading StoragePool: %s", err) } + if err := d.Set("zone", flattenNetappStoragePoolZone(res["zone"], d, config)); err != nil { + return fmt.Errorf("Error reading StoragePool: %s", err) + } + if err := d.Set("replica_zone", flattenNetappStoragePoolReplicaZone(res["replicaZone"], d, config)); err != nil { + return fmt.Errorf("Error reading StoragePool: %s", err) + } if err := d.Set("allow_auto_tiering", flattenNetappStoragePoolAllowAutoTiering(res["allowAutoTiering"], d, config)); err != nil { return fmt.Errorf("Error reading StoragePool: %s", err) } @@ -409,6 +440,18 @@ func resourceNetappStoragePoolUpdate(d *schema.ResourceData, meta interface{}) e } else if v, ok := d.GetOkExists("active_directory"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, activeDirectoryProp)) { obj["activeDirectory"] = activeDirectoryProp } + zoneProp, err := expandNetappStoragePoolZone(d.Get("zone"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("zone"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, zoneProp)) { + obj["zone"] = zoneProp + } + replicaZoneProp, err := expandNetappStoragePoolReplicaZone(d.Get("replica_zone"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("replica_zone"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, replicaZoneProp)) { + obj["replicaZone"] = replicaZoneProp + } labelsProp, err := expandNetappStoragePoolEffectiveLabels(d.Get("effective_labels"), d, config) if err != nil { return err @@ -437,6 +480,14 @@ func resourceNetappStoragePoolUpdate(d *schema.ResourceData, meta interface{}) e updateMask = append(updateMask, "activeDirectory") } + if d.HasChange("zone") { + updateMask = append(updateMask, "zone") + } + + if d.HasChange("replica_zone") { + updateMask = append(updateMask, "replicaZone") + } + if d.HasChange("effective_labels") { updateMask = append(updateMask, "labels") } @@ -692,6 +743,14 @@ func flattenNetappStoragePoolEncryptionType(v interface{}, d *schema.ResourceDat return v } +func flattenNetappStoragePoolZone(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNetappStoragePoolReplicaZone(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + func flattenNetappStoragePoolAllowAutoTiering(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { return v } @@ -743,6 +802,14 @@ func expandNetappStoragePoolLdapEnabled(v interface{}, d tpgresource.TerraformRe return v, nil } +func expandNetappStoragePoolZone(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandNetappStoragePoolReplicaZone(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + func expandNetappStoragePoolAllowAutoTiering(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { return v, nil } diff --git a/google/services/netapp/resource_netapp_storage_pool_test.go b/google/services/netapp/resource_netapp_storage_pool_test.go index f6bfe1431f4..e4815236d29 100644 --- a/google/services/netapp/resource_netapp_storage_pool_test.go +++ b/google/services/netapp/resource_netapp_storage_pool_test.go @@ -3,10 +3,11 @@ package netapp_test import ( - "testing" - "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/terraform" "github.com/hashicorp/terraform-provider-google/google/acctest" + "testing" + "time" ) func TestAccNetappStoragePool_storagePoolCreateExample_update(t *testing.T) { @@ -193,3 +194,126 @@ resource "google_netapp_storage_pool" "test_pool" { } `, context) } + +func TestAccNetappStoragePool_FlexRegionalStoragePoolCreateExample_update(t *testing.T) { + context := map[string]interface{}{ + "network_name": acctest.BootstrapSharedServiceNetworkingConnection(t, "gcnv-network-config-1", acctest.ServiceNetworkWithParentService("netapp.servicenetworking.goog")), + "random_suffix": acctest.RandString(t, 10), + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckNetappStoragePoolDestroyProducer(t), + ExternalProviders: map[string]resource.ExternalProvider{ + "time": {}, + }, + Steps: []resource.TestStep{ + { + Config: testAccNetappStoragePool_FlexRegionalStoragePoolCreateExample_full(context), + }, + { + ResourceName: "google_netapp_storage_pool.test_pool", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"location", "name", "labels", "terraform_labels"}, + }, + { + Config: testAccNetappStoragePool_FlexRegionalStoragePoolCreateExample_switchZone(context), + Check: testAccNetappStoragePool_FlexRegionalStoragePoolCreateExample_sleep_5_mins(), + }, + { + ResourceName: "google_netapp_storage_pool.test_pool", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"location", "name", "labels", "terraform_labels"}, + }, + { + Config: testAccNetappStoragePool_FlexRegionalStoragePoolCreateExample_switchBackZone(context), + }, + { + ResourceName: "google_netapp_storage_pool.test_pool", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"location", "name", "labels", "terraform_labels"}, + }, + }, + }) +} + +func testAccNetappStoragePool_FlexRegionalStoragePoolCreateExample_full(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_netapp_storage_pool" "test_pool" { + name = "tf-test-pool%{random_suffix}" + location = "us-east1" + service_level = "FLEX" + capacity_gib = "2048" + network = data.google_compute_network.default.id + zone = "us-east1-c" + replica_zone = "us-east1-b" +} + +resource "time_sleep" "wait_5_minutes" { + depends_on = [google_netapp_storage_pool.test_pool] + destroy_duration = "5m" +} + +data "google_compute_network" "default" { + name = "%{network_name}" +} +`, context) +} + +func testAccNetappStoragePool_FlexRegionalStoragePoolCreateExample_switchZone(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_netapp_storage_pool" "test_pool" { + name = "tf-test-pool%{random_suffix}" + location = "us-east1" + service_level = "FLEX" + capacity_gib = "2048" + network = data.google_compute_network.default.id + zone = "us-east1-b" + replica_zone = "us-east1-c" +} + +resource "time_sleep" "wait_5_minutes" { + depends_on = [google_netapp_storage_pool.test_pool] + destroy_duration = "5m" +} + +data "google_compute_network" "default" { + name = "%{network_name}" +} +`, context) +} + +func testAccNetappStoragePool_FlexRegionalStoragePoolCreateExample_sleep_5_mins() resource.TestCheckFunc { + return func(s *terraform.State) error { + // wait 5 minutes before executing the switchback due to api zone switch issues + time.Sleep(5 * time.Minute) + return nil + } +} + +func testAccNetappStoragePool_FlexRegionalStoragePoolCreateExample_switchBackZone(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_netapp_storage_pool" "test_pool" { + name = "tf-test-pool%{random_suffix}" + location = "us-east1" + service_level = "FLEX" + capacity_gib = "2048" + network = data.google_compute_network.default.id + zone = "us-east1-c" + replica_zone = "us-east1-b" +} + +resource "time_sleep" "wait_5_minutes" { + depends_on = [google_netapp_storage_pool.test_pool] + destroy_duration = "5m" +} + +data "google_compute_network" "default" { + name = "%{network_name}" +} +`, context) +} diff --git a/google/services/netapp/resource_netapp_volume.go b/google/services/netapp/resource_netapp_volume.go index 90c30f30aa8..af332e26bf2 100644 --- a/google/services/netapp/resource_netapp_volume.go +++ b/google/services/netapp/resource_netapp_volume.go @@ -538,6 +538,11 @@ Format for SMB volumes: '\\\\netbios_prefix-four_random_hex_letters.domain_name\ Computed: true, Description: `Name of the Private Service Access allocated range. Inherited from storage pool.`, }, + "replica_zone": { + Type: schema.TypeString, + Computed: true, + Description: `Specifies the replica zone for regional volume.`, + }, "service_level": { Type: schema.TypeString, Computed: true, @@ -565,6 +570,11 @@ Format for SMB volumes: '\\\\netbios_prefix-four_random_hex_letters.domain_name\ Computed: true, Description: `Used capacity of the volume (in GiB). This is computed periodically and it does not represent the realtime usage.`, }, + "zone": { + Type: schema.TypeString, + Computed: true, + Description: `Specifies the active zone for regional volume.`, + }, "deletion_policy": { Type: schema.TypeString, Optional: true, @@ -896,6 +906,12 @@ func resourceNetappVolumeRead(d *schema.ResourceData, meta interface{}) error { if err := d.Set("backup_config", flattenNetappVolumeBackupConfig(res["backupConfig"], d, config)); err != nil { return fmt.Errorf("Error reading Volume: %s", err) } + if err := d.Set("zone", flattenNetappVolumeZone(res["zone"], d, config)); err != nil { + return fmt.Errorf("Error reading Volume: %s", err) + } + if err := d.Set("replica_zone", flattenNetappVolumeReplicaZone(res["replicaZone"], d, config)); err != nil { + return fmt.Errorf("Error reading Volume: %s", err) + } if err := d.Set("large_capacity", flattenNetappVolumeLargeCapacity(res["largeCapacity"], d, config)); err != nil { return fmt.Errorf("Error reading Volume: %s", err) } @@ -1762,6 +1778,14 @@ func flattenNetappVolumeBackupConfigScheduledBackupEnabled(v interface{}, d *sch return v } +func flattenNetappVolumeZone(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNetappVolumeReplicaZone(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + func flattenNetappVolumeLargeCapacity(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { return v } diff --git a/website/docs/r/netapp_storage_pool.html.markdown b/website/docs/r/netapp_storage_pool.html.markdown index 78504d816b5..b1c7ba93a63 100644 --- a/website/docs/r/netapp_storage_pool.html.markdown +++ b/website/docs/r/netapp_storage_pool.html.markdown @@ -40,7 +40,6 @@ and `replica_zone` values to reflect the current state, or Terraform will initia the next apply. You can trigger a manual [zone switch](https://cloud.google.com/netapp/volumes/docs/configure-and-use/storage-pools/edit-or-delete-storage-pool#switch_active_and_replica_zones) via Terraform by swapping the value of the `zone` and `replica_zone` parameters in your HCL code. -Note : Regional FLEX storage pool are supported in beta provider currently. To get more information about StoragePool, see: @@ -161,13 +160,13 @@ The following arguments are supported: using security identifiers for NFSv4.1 or principal names for kerberized NFSv4.1. * `zone` - - (Optional, [Beta](https://terraform.io/docs/providers/google/guides/provider_versions.html)) + (Optional) Specifies the active zone for regional Flex pools. `zone` and `replica_zone` values can be swapped to initiate a [zone switch](https://cloud.google.com/netapp/volumes/docs/configure-and-use/storage-pools/edit-or-delete-storage-pool#switch_active_and_replica_zones). If you want to create a zonal Flex pool, specify a zone name for `location` and omit `zone`. * `replica_zone` - - (Optional, [Beta](https://terraform.io/docs/providers/google/guides/provider_versions.html)) + (Optional) Specifies the replica zone for regional Flex pools. `zone` and `replica_zone` values can be swapped to initiate a [zone switch](https://cloud.google.com/netapp/volumes/docs/configure-and-use/storage-pools/edit-or-delete-storage-pool#switch_active_and_replica_zones). diff --git a/website/docs/r/netapp_volume.html.markdown b/website/docs/r/netapp_volume.html.markdown index 5de0d6a1015..2138ca79ce6 100644 --- a/website/docs/r/netapp_volume.html.markdown +++ b/website/docs/r/netapp_volume.html.markdown @@ -414,11 +414,9 @@ In addition to the arguments listed above, the following computed attributes are Structure is [documented below](#nested_mount_options). * `zone` - - ([Beta](https://terraform.io/docs/providers/google/guides/provider_versions.html)) Specifies the active zone for regional volume. * `replica_zone` - - ([Beta](https://terraform.io/docs/providers/google/guides/provider_versions.html)) Specifies the replica zone for regional volume. * `cold_tier_size_gib` -