From 6a3c533898d05923846aad569d0a561a03f942ab Mon Sep 17 00:00:00 2001 From: Modular Magician Date: Fri, 31 Jan 2025 20:55:30 +0000 Subject: [PATCH] Adding replication field for Filestore Instance (#11897) [upstream:383b394588fdd1b7d971a7f5b6f0321dd1c65d5d] Signed-off-by: Modular Magician --- .changelog/11897.txt | 3 + .../filestore/resource_filestore_instance.go | 119 ++++++++++++++++++ ...rce_filestore_instance_generated_meta.yaml | 10 ++ ...ource_filestore_instance_generated_test.go | 6 +- .../resource_filestore_instance_test.go | 71 +++++++++++ .../docs/r/filestore_instance.html.markdown | 54 ++++++++ 6 files changed, 260 insertions(+), 3 deletions(-) create mode 100644 .changelog/11897.txt diff --git a/.changelog/11897.txt b/.changelog/11897.txt new file mode 100644 index 0000000000..48e73714d2 --- /dev/null +++ b/.changelog/11897.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +filestore: added `initial_replication` field for peer instance configuration and `effective_replication` output for replication configuration output to `google_filestore_instance` +``` \ No newline at end of file diff --git a/google-beta/services/filestore/resource_filestore_instance.go b/google-beta/services/filestore/resource_filestore_instance.go index e1e21427a0..e6912e35aa 100644 --- a/google-beta/services/filestore/resource_filestore_instance.go +++ b/google-beta/services/filestore/resource_filestore_instance.go @@ -232,6 +232,39 @@ Possible values include: STANDARD, PREMIUM, BASIC_HDD, BASIC_SSD, HIGH_SCALE_SSD Optional: true, Description: `A description of the instance.`, }, + "initial_replication": { + Type: schema.TypeList, + Optional: true, + ForceNew: true, + Description: `Replication configuration, once set, this cannot be updated. +Addtionally this should be specified on the replica instance only, indicating the active as the peer_instance`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "replicas": { + Type: schema.TypeList, + Optional: true, + Description: `The replication role.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "peer_instance": { + Type: schema.TypeString, + Required: true, + Description: `The peer instance.`, + }, + }, + }, + }, + "role": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: verify.ValidateEnum([]string{"ROLE_UNSPECIFIED", "ACTIVE", "STANDBY", ""}), + Description: `The replication role. Default value: "STANDBY" Possible values: ["ROLE_UNSPECIFIED", "ACTIVE", "STANDBY"]`, + Default: "STANDBY", + }, + }, + }, + }, "kms_key_name": { Type: schema.TypeString, Optional: true, @@ -353,6 +386,44 @@ resource, see the 'google_tags_tag_value' resource.`, Description: `All of labels (key/value pairs) present on the resource in GCP, including the labels configured through Terraform, other clients and services.`, Elem: &schema.Schema{Type: schema.TypeString}, }, + "effective_replication": { + Type: schema.TypeList, + Computed: true, + Description: `Output only fields for replication configuration.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "replicas": { + Type: schema.TypeList, + Optional: true, + Description: `The replication role.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "last_active_sync_time": { + Type: schema.TypeString, + Computed: true, + Description: `Output only. The timestamp of the latest replication snapshot taken on the active instance and is already replicated safely. +A timestamp in RFC3339 UTC "Zulu" format, with nanosecond resolution and up to nine fractional digits. +Examples: "2014-10-02T15:01:23Z" and "2014-10-02T15:01:23.045123456Z"`, + }, + "state": { + Type: schema.TypeString, + Computed: true, + Description: `Output only. The replica state`, + }, + "state_reasons": { + Type: schema.TypeList, + Computed: true, + Description: `Output only. Additional information about the replication state, if available.`, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + }, + }, + }, + }, + }, + }, "etag": { Type: schema.TypeString, Computed: true, @@ -615,6 +686,9 @@ func resourceFilestoreInstanceRead(d *schema.ResourceData, meta interface{}) err if err := d.Set("performance_config", flattenFilestoreInstancePerformanceConfig(res["performanceConfig"], d, config)); err != nil { return fmt.Errorf("Error reading Instance: %s", err) } + if err := d.Set("effective_replication", flattenFilestoreInstanceEffectiveReplication(res["replication"], d, config)); err != nil { + return fmt.Errorf("Error reading Instance: %s", err) + } if err := d.Set("terraform_labels", flattenFilestoreInstanceTerraformLabels(res["labels"], d, config)); err != nil { return fmt.Errorf("Error reading Instance: %s", err) } @@ -1117,6 +1191,51 @@ func flattenFilestoreInstancePerformanceConfigFixedIopsMaxIops(v interface{}, d return v // let terraform core handle it otherwise } +func flattenFilestoreInstanceEffectiveReplication(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + if v == nil { + return nil + } + original := v.(map[string]interface{}) + if len(original) == 0 { + return nil + } + transformed := make(map[string]interface{}) + transformed["replicas"] = + flattenFilestoreInstanceEffectiveReplicationReplicas(original["replicas"], d, config) + return []interface{}{transformed} +} +func flattenFilestoreInstanceEffectiveReplicationReplicas(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + if v == nil { + return v + } + l := v.([]interface{}) + transformed := make([]interface{}, 0, len(l)) + for _, raw := range l { + original := raw.(map[string]interface{}) + if len(original) < 1 { + // Do not include empty json objects coming back from the api + continue + } + transformed = append(transformed, map[string]interface{}{ + "state": flattenFilestoreInstanceEffectiveReplicationReplicasState(original["state"], d, config), + "state_reasons": flattenFilestoreInstanceEffectiveReplicationReplicasStateReasons(original["stateReasons"], d, config), + "last_active_sync_time": flattenFilestoreInstanceEffectiveReplicationReplicasLastActiveSyncTime(original["lastActiveSyncTime"], d, config), + }) + } + return transformed +} +func flattenFilestoreInstanceEffectiveReplicationReplicasState(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenFilestoreInstanceEffectiveReplicationReplicasStateReasons(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenFilestoreInstanceEffectiveReplicationReplicasLastActiveSyncTime(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + func flattenFilestoreInstanceTerraformLabels(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { if v == nil { return v diff --git a/google-beta/services/filestore/resource_filestore_instance_generated_meta.yaml b/google-beta/services/filestore/resource_filestore_instance_generated_meta.yaml index 8198b60b00..97e9036082 100644 --- a/google-beta/services/filestore/resource_filestore_instance_generated_meta.yaml +++ b/google-beta/services/filestore/resource_filestore_instance_generated_meta.yaml @@ -10,6 +10,12 @@ fields: - field: 'description' - field: 'effective_labels' provider_only: true + - field: 'effective_replication.replicas.last_active_sync_time' + api_field: 'replication.replicas.last_active_sync_time' + - field: 'effective_replication.replicas.state' + api_field: 'replication.replicas.state' + - field: 'effective_replication.replicas.state_reasons' + api_field: 'replication.replicas.state_reasons' - field: 'etag' - field: 'file_shares.capacity_gb' - field: 'file_shares.name' @@ -19,6 +25,10 @@ fields: - field: 'file_shares.nfs_export_options.ip_ranges' - field: 'file_shares.nfs_export_options.squash_mode' - field: 'file_shares.source_backup' + - field: 'initial_replication.replicas.peer_instance' + provider_only: true + - field: 'initial_replication.role' + provider_only: true - field: 'kms_key_name' - field: 'labels' - field: 'location' diff --git a/google-beta/services/filestore/resource_filestore_instance_generated_test.go b/google-beta/services/filestore/resource_filestore_instance_generated_test.go index 12117f1bd5..6ee427a32d 100644 --- a/google-beta/services/filestore/resource_filestore_instance_generated_test.go +++ b/google-beta/services/filestore/resource_filestore_instance_generated_test.go @@ -49,7 +49,7 @@ func TestAccFilestoreInstance_filestoreInstanceBasicExample(t *testing.T) { ResourceName: "google_filestore_instance.instance", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"labels", "location", "name", "tags", "terraform_labels", "zone"}, + ImportStateVerifyIgnore: []string{"initial_replication", "labels", "location", "name", "tags", "terraform_labels", "zone"}, }, }, }) @@ -94,7 +94,7 @@ func TestAccFilestoreInstance_filestoreInstanceFullExample(t *testing.T) { ResourceName: "google_filestore_instance.instance", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"labels", "location", "name", "tags", "terraform_labels", "zone"}, + ImportStateVerifyIgnore: []string{"initial_replication", "labels", "location", "name", "tags", "terraform_labels", "zone"}, }, }, }) @@ -154,7 +154,7 @@ func TestAccFilestoreInstance_filestoreInstanceProtocolExample(t *testing.T) { ResourceName: "google_filestore_instance.instance", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"labels", "location", "name", "tags", "terraform_labels", "zone"}, + ImportStateVerifyIgnore: []string{"initial_replication", "labels", "location", "name", "tags", "terraform_labels", "zone"}, }, }, }) diff --git a/google-beta/services/filestore/resource_filestore_instance_test.go b/google-beta/services/filestore/resource_filestore_instance_test.go index c286e96198..b4810989d9 100644 --- a/google-beta/services/filestore/resource_filestore_instance_test.go +++ b/google-beta/services/filestore/resource_filestore_instance_test.go @@ -462,3 +462,74 @@ tags = {`, name) l += fmt.Sprintf("}\n}") return r + l } + +func TestAccFilestoreInstance_replication(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "random_suffix": acctest.RandString(t, 10), + "location_1": "us-central1", + "location_2": "us-west1", + "tier": "ENTERPRISE", + } + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckFilestoreInstanceDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccFilestoreInstance_replication(context), + }, + { + ResourceName: "google_filestore_instance.replica-instance", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"zone", "initial_replication"}, + }, + }, + }) +} + +func testAccFilestoreInstance_replication(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_filestore_instance" "instance" { + name = "tf-instance-%{random_suffix}" + location = "%{location_1}" + tier = "%{tier}" + description = "An instance created during testing." + + file_shares { + capacity_gb = 1024 + name = "share" + } + + networks { + network = "default" + modes = ["MODE_IPV4"] + } +} + +resource "google_filestore_instance" "replica-instance" { + name = "tf-rinstance-%{random_suffix}" + location = "%{location_2}" + tier = "%{tier}" + description = "An replica instance created during testing." + + file_shares { + capacity_gb = 1024 + name = "share" + } + + networks { + network = "default" + modes = ["MODE_IPV4"] + } + + initial_replication { + replicas { + peer_instance = google_filestore_instance.instance.id + } + } +} +`, context) +} diff --git a/website/docs/r/filestore_instance.html.markdown b/website/docs/r/filestore_instance.html.markdown index 17b82ceab8..30ddcbe0f6 100644 --- a/website/docs/r/filestore_instance.html.markdown +++ b/website/docs/r/filestore_instance.html.markdown @@ -322,6 +322,12 @@ The following arguments are supported: will trigger recreation. To apply tags to an existing resource, see the `google_tags_tag_value` resource. +* `initial_replication` - + (Optional) + Replication configuration, once set, this cannot be updated. + Addtionally this should be specified on the replica instance only, indicating the active as the peer_instance + Structure is [documented below](#nested_initial_replication). + * `zone` - (Optional, Deprecated) The name of the Filestore zone of the instance. @@ -369,6 +375,26 @@ The following arguments are supported: The number of IOPS to provision for the instance. max_iops must be in multiple of 1000. +The `initial_replication` block supports: + +* `role` - + (Optional) + The replication role. + Default value is `STANDBY`. + Possible values are: `ROLE_UNSPECIFIED`, `ACTIVE`, `STANDBY`. + +* `replicas` - + (Optional) + The replication role. + Structure is [documented below](#nested_initial_replication_replicas). + + +The `replicas` block supports: + +* `peer_instance` - + (Required) + The peer instance. + ## Attributes Reference In addition to the arguments listed above, the following computed attributes are exported: @@ -382,6 +408,10 @@ In addition to the arguments listed above, the following computed attributes are Server-specified ETag for the instance resource to prevent simultaneous updates from overwriting each other. +* `effective_replication` - + Output only fields for replication configuration. + Structure is [documented below](#nested_effective_replication). + * `terraform_labels` - The combination of labels configured directly on the resource and default labels configured on the provider. @@ -390,6 +420,30 @@ In addition to the arguments listed above, the following computed attributes are All of labels (key/value pairs) present on the resource in GCP, including the labels configured through Terraform, other clients and services. +The `effective_replication` block contains: + +* `replicas` - + (Optional) + The replication role. + Structure is [documented below](#nested_effective_replication_replicas). + + +The `replicas` block supports: + +* `state` - + (Output) + Output only. The replica state + +* `state_reasons` - + (Output) + Output only. Additional information about the replication state, if available. + +* `last_active_sync_time` - + (Output) + Output only. The timestamp of the latest replication snapshot taken on the active instance and is already replicated safely. + A timestamp in RFC3339 UTC "Zulu" format, with nanosecond resolution and up to nine fractional digits. + Examples: "2014-10-02T15:01:23Z" and "2014-10-02T15:01:23.045123456Z" + ## Timeouts This resource provides the following