From 4a26e16457d6fca1592d5d5a795ebe1099c6c2b6 Mon Sep 17 00:00:00 2001 From: Roopkamal Tyagi Date: Mon, 3 Jun 2024 13:16:11 +0000 Subject: [PATCH 1/5] Adding support for google_netapp_backup resource in netapp volumes --- mmv1/products/netapp/backup.yaml | 145 ++++++++++++++++++ .../terraform/examples/netapp_backup.tf.erb | 36 +++++ .../netapp/resource_netapp_backup_test.go | 91 +++++++++++ 3 files changed, 272 insertions(+) create mode 100644 mmv1/products/netapp/backup.yaml create mode 100644 mmv1/templates/terraform/examples/netapp_backup.tf.erb create mode 100644 mmv1/third_party/terraform/services/netapp/resource_netapp_backup_test.go diff --git a/mmv1/products/netapp/backup.yaml b/mmv1/products/netapp/backup.yaml new file mode 100644 index 000000000000..42350f207d6f --- /dev/null +++ b/mmv1/products/netapp/backup.yaml @@ -0,0 +1,145 @@ +# Copyright 2023 Google Inc. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +--- !ruby/object:Api::Resource +name: 'backup' +description: | + NetApp Volumes supports volume backups, which are copies of your volumes + stored independently from the volume. Backups are stored in backup vaults, + which are containers for backups. If a volume is lost or deleted, you can + use backups to restore your data to a new volume. + + When you create the first backup of a volume, all of the volume's used + data is sent to the backup vault. Subsequent backups of the same volume + only include data that has changed from the previous backup. This allows + for fast incremental-forever backups and reduces the required capacity + inside the backup vault. + + You can create manual and scheduled backups. Manual backups can be taken + from a volume or from an existing volume snapshot. Scheduled backups + require a backup policy. +references: !ruby/object:Api::Resource::ReferenceLinks + guides: + 'Documentation': 'https://cloud.google.com/netapp/volumes/docs/protect-data/about-volume-backups' + api: 'https://cloud.google.com/netapp/volumes/docs/reference/rest/v1/projects.locations.backupVaults.backups' +base_url: projects/{{project}}/locations/{{location}}/backupVaults/{{vault_name}}/backups +self_link: projects/{{project}}/locations/{{location}}/backupVaults/{{vault_name}}/backups/{{name}} +create_url: projects/{{project}}/locations/{{location}}/backupVaults/{{vault_name}}/backups?backupId={{name}} +create_verb: :POST +update_url: projects/{{project}}/locations/{{location}}/backupVaults/{{vault_name}}/backups/{{name}} +update_verb: :PATCH +update_mask: true +delete_url: projects/{{project}}/locations/{{location}}/backupVaults/{{vault_name}}/backups/{{name}} +delete_verb: :DELETE +autogen_async: true +async: !ruby/object:Api::OpAsync + operation: !ruby/object:Api::OpAsync::Operation + base_url: '{{op_id}}' +id_format: 'projects/{{project}}/locations/{{location}}/backupVaults/{{vault_name}}/backups/{{name}}' +import_format: ['projects/{{project}}/locations/{{location}}/backupVaults/{{vault_name}}/backups/{{name}}'] +examples: + - !ruby/object:Provider::Terraform::Examples + name: 'netapp_backup' + primary_resource_id: 'test_backup' + vars: + pool_name: 'backup-pool' + volume_name: 'backup-volume' + backup_vault_name: 'backup-vault' + backup_name: 'test-backup' + test_vars_overrides: + network_name: 'acctest.BootstrapSharedServiceNetworkingConnection(t, "gcnv-network-config-1", acctest.ServiceNetworkWithParentService("netapp.servicenetworking.goog"))' +parameters: + - !ruby/object:Api::Type::String + name: 'location' + required: true + immutable: true + url_param_only: true + description: | + Location of the backup. + - !ruby/object:Api::Type::String + name: 'vault_name' + required: true + immutable: true + url_param_only: true + description: | + Name of the backup vault to store the backup in. + - !ruby/object:Api::Type::String + name: 'name' + description: | + The resource name of the backup. Needs to be unique per location. + required: true + immutable: true + url_param_only: true +properties: + - !ruby/object:Api::Type::Enum + name: 'state' + description: | + The state of the Backup Vault. + values: + - :STATE_UNSPECIFIED + - :CREATING + - :UPLOADING + - :READY + - :DELETING + - :ERROR + - :UPDATING + output: true + - !ruby/object:Api::Type::String + name: 'description' + description: | + An optional description of this resource. + required: false + - !ruby/object:Api::Type::String + name: 'volumeUsageBytes' + description: | + Size of the file system when the backup was created. When creating a new volume from the backup, the volume capacity will have to be at least as big. + output: true + - !ruby/object:Api::Type::Enum + name: 'backupType' + description: | + Type of backup, manually created or created by a backup policy. + values: + - :TYPE_UNSPECIFIED + - :MANUAL + - :SCHEDULED + output: true + - !ruby/object:Api::Type::String + name: 'sourceVolume' + description: | + ID of volumes this backup belongs to. Format: `projects/{{projects_id}}/locations/{{location}}/volumes/{{name}}`` + immutable: true + diff_suppress_func: tpgresource.ProjectNumberDiffSuppress + - !ruby/object:Api::Type::String + name: 'createTime' + description: | + Create time of the backup. A timestamp in RFC3339 UTC "Zulu" format. Examples: "2023-06-22T09:13:01.617Z". + output: true + - !ruby/object:Api::Type::KeyValueLabels + name: labels + description: | + Labels as key value pairs. Example: `{ "owner": "Bob", "department": "finance", "purpose": "testing" }`. + required: false + - !ruby/object:Api::Type::String + name: 'chainStorageBytes' + description: | + Backups of a volume build incrementally on top of each other. They form a "backup chain". + Total size of all backups in a chain in bytes = baseline backup size + sum(incremental backup size) + output: true + - !ruby/object:Api::Type::String + name: 'sourceSnapshot' + description: | + If specified, backup will be created from the given snapshot. If not specified, + there will be a new snapshot taken to initiate the backup creation. + Format: `projects/{{projectId}}/locations/{{location}}/volumes/{{volumename}}/snapshots/{{snapshotname}}`` + required: false + diff_suppress_func: tpgresource.ProjectNumberDiffSuppress diff --git a/mmv1/templates/terraform/examples/netapp_backup.tf.erb b/mmv1/templates/terraform/examples/netapp_backup.tf.erb new file mode 100644 index 000000000000..e772b10d703e --- /dev/null +++ b/mmv1/templates/terraform/examples/netapp_backup.tf.erb @@ -0,0 +1,36 @@ +data "google_compute_network" "default" { + name = "<%= ctx[:vars]['network_name'] %>" +} + +resource "google_netapp_storage_pool" "default" { + name = "<%= ctx[:vars]['pool_name'] %>" + location = "us-central1" + service_level = "PREMIUM" + capacity_gib = "2048" + network = data.google_compute_network.default.id +} + +resource "google_netapp_volume" "default" { + name = "<%= ctx[:vars]['volume_name'] %>" + location = google_netapp_storage_pool.default.location + capacity_gib = "100" + share_name = "<%= ctx[:vars]['volume_name'] %>" + storage_pool = google_netapp_storage_pool.default.name + protocols = ["NFSV3"] + deletion_policy = "FORCE" + backup_config { + backup_vault = google_netapp_backup_vault.default.id + } +} + +resource "google_netapp_backup_vault" "default" { + name = "<%= ctx[:vars]['backup_vault_name'] %>" + location = google_netapp_storage_pool.default.location +} + +resource "google_netapp_backup" "<%= ctx[:primary_resource_id] %>" { + name = "<%= ctx[:vars]['backup_name'] %>" + location = google_netapp_backup_vault.default.location + vault_name = google_netapp_backup_vault.default.name + source_volume = google_netapp_volume.default.id +} diff --git a/mmv1/third_party/terraform/services/netapp/resource_netapp_backup_test.go b/mmv1/third_party/terraform/services/netapp/resource_netapp_backup_test.go new file mode 100644 index 000000000000..f31234583f6d --- /dev/null +++ b/mmv1/third_party/terraform/services/netapp/resource_netapp_backup_test.go @@ -0,0 +1,91 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package netapp_test + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-provider-google/google/acctest" +) + +func TestAccNetappbackup_netappBackupFull(t *testing.T) { + t.Parallel() + + 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: testAccCheckNetappbackupDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccNetappbackup_netappBackupFromVolumeSnapshot(context), + }, + { + ResourceName: "google_netapp_backup.test_backup", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "location", "name", "terraform_labels", "vault_name"}, + }, + }, + }) +} + +func testAccNetappbackup_netappBackupFromVolumeSnapshot(context map[string]interface{}) string { + return acctest.Nprintf(` +data "google_compute_network" "default" { + name = "%{network_name}" +} + +resource "google_netapp_storage_pool" "default" { + name = "tf-test-backup-pool%{random_suffix}" + location = "us-central1" + service_level = "PREMIUM" + capacity_gib = "2048" + network = data.google_compute_network.default.id +} + +resource "google_netapp_volume" "default" { + name = "tf-test-backup-volume%{random_suffix}" + location = google_netapp_storage_pool.default.location + capacity_gib = "100" + share_name = "tf-test-backup-volume%{random_suffix}" + storage_pool = google_netapp_storage_pool.default.name + protocols = ["NFSV3"] + deletion_policy = "FORCE" + backup_config { + backup_vault = google_netapp_backup_vault.default.id + } +} + +resource "google_netapp_backup_vault" "default" { + name = "tf-test-backup-vault%{random_suffix}" + location = google_netapp_storage_pool.default.location +} + +resource "google_netapp_volume_snapshot" "default" { + depends_on = [google_netapp_volume.default] + location = google_netapp_volume.default.location + volume_name = google_netapp_volume.default.name + description = "This is a test description" + name = "testvolumesnap%{random_suffix}" + labels = { + key= "test" + value= "snapshot" + } + } + +resource "google_netapp_backup" "test_backup" { + name = "tf-test-test-backup%{random_suffix}" + source_volume = google_netapp_volume.default.id + location = google_netapp_backup_vault.default.location + vault_name = google_netapp_backup_vault.default.name + source_snapshot = google_netapp_volume_snapshot.default.id +} +`, context) +} From 16b5c4daede45942a3d1b2642fed85969c7ba07f Mon Sep 17 00:00:00 2001 From: Roopkamal Tyagi Date: Mon, 3 Jun 2024 15:04:53 +0000 Subject: [PATCH 2/5] Removing parallel exection of the backup resource test to avoid failures due to to 1 vault per region limit --- .../terraform/services/netapp/resource_netapp_backup_test.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/mmv1/third_party/terraform/services/netapp/resource_netapp_backup_test.go b/mmv1/third_party/terraform/services/netapp/resource_netapp_backup_test.go index f31234583f6d..aba8ee63ccda 100644 --- a/mmv1/third_party/terraform/services/netapp/resource_netapp_backup_test.go +++ b/mmv1/third_party/terraform/services/netapp/resource_netapp_backup_test.go @@ -11,8 +11,6 @@ import ( ) func TestAccNetappbackup_netappBackupFull(t *testing.T) { - t.Parallel() - context := map[string]interface{}{ "network_name": acctest.BootstrapSharedServiceNetworkingConnection(t, "gcnv-network-config-1", acctest.ServiceNetworkWithParentService("netapp.servicenetworking.goog")), "random_suffix": acctest.RandString(t, 10), From 6830d34384532e9efbb63d742ce5f3b8b58a0330 Mon Sep 17 00:00:00 2001 From: Roopkamal Tyagi Date: Mon, 3 Jun 2024 17:04:40 +0000 Subject: [PATCH 3/5] Adding description,label fields in the google_netapp_backup test --- .../terraform/services/netapp/resource_netapp_backup_test.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/mmv1/third_party/terraform/services/netapp/resource_netapp_backup_test.go b/mmv1/third_party/terraform/services/netapp/resource_netapp_backup_test.go index aba8ee63ccda..2bfc296f62fe 100644 --- a/mmv1/third_party/terraform/services/netapp/resource_netapp_backup_test.go +++ b/mmv1/third_party/terraform/services/netapp/resource_netapp_backup_test.go @@ -80,10 +80,15 @@ resource "google_netapp_volume_snapshot" "default" { resource "google_netapp_backup" "test_backup" { name = "tf-test-test-backup%{random_suffix}" + description = "This is a test backup" source_volume = google_netapp_volume.default.id location = google_netapp_backup_vault.default.location vault_name = google_netapp_backup_vault.default.name source_snapshot = google_netapp_volume_snapshot.default.id + labels = { + key= "test" + value= "backup" + } } `, context) } From 0f8cec151cc642d4f0709cce5b782d34af4c5d86 Mon Sep 17 00:00:00 2001 From: Roopkamal Tyagi Date: Thu, 6 Jun 2024 12:47:58 +0000 Subject: [PATCH 4/5] Fixing resource description Moving output only fields to string Adding update test for the resource --- mmv1/products/netapp/backup.yaml | 22 ++---- .../netapp/resource_netapp_backup_test.go | 70 ++++++++++++++++++- 2 files changed, 74 insertions(+), 18 deletions(-) diff --git a/mmv1/products/netapp/backup.yaml b/mmv1/products/netapp/backup.yaml index 42350f207d6f..45685fec52c4 100644 --- a/mmv1/products/netapp/backup.yaml +++ b/mmv1/products/netapp/backup.yaml @@ -81,37 +81,25 @@ parameters: immutable: true url_param_only: true properties: - - !ruby/object:Api::Type::Enum + - !ruby/object:Api::Type::String name: 'state' description: | - The state of the Backup Vault. - values: - - :STATE_UNSPECIFIED - - :CREATING - - :UPLOADING - - :READY - - :DELETING - - :ERROR - - :UPDATING + The state of the Backup Vault. Possible Values : [STATE_UNSPECIFIED, CREATING, UPLOADING, READY, DELETING, ERROR, UPDATING] output: true - !ruby/object:Api::Type::String name: 'description' description: | - An optional description of this resource. + A description of the backup with 2048 characters or less. Requests with longer descriptions will be rejected. required: false - !ruby/object:Api::Type::String name: 'volumeUsageBytes' description: | Size of the file system when the backup was created. When creating a new volume from the backup, the volume capacity will have to be at least as big. output: true - - !ruby/object:Api::Type::Enum + - !ruby/object:Api::Type::String name: 'backupType' description: | - Type of backup, manually created or created by a backup policy. - values: - - :TYPE_UNSPECIFIED - - :MANUAL - - :SCHEDULED + Type of backup, manually created or created by a backup policy. Possible Values : [TYPE_UNSPECIFIED, MANUAL, SCHEDULED] output: true - !ruby/object:Api::Type::String name: 'sourceVolume' diff --git a/mmv1/third_party/terraform/services/netapp/resource_netapp_backup_test.go b/mmv1/third_party/terraform/services/netapp/resource_netapp_backup_test.go index 2bfc296f62fe..d12267b66a17 100644 --- a/mmv1/third_party/terraform/services/netapp/resource_netapp_backup_test.go +++ b/mmv1/third_party/terraform/services/netapp/resource_netapp_backup_test.go @@ -10,7 +10,7 @@ import ( "github.com/hashicorp/terraform-provider-google/google/acctest" ) -func TestAccNetappbackup_netappBackupFull(t *testing.T) { +func TestAccNetappbackup_netappBackupFull_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), @@ -30,6 +30,15 @@ func TestAccNetappbackup_netappBackupFull(t *testing.T) { ImportStateVerify: true, ImportStateVerifyIgnore: []string{"labels", "location", "name", "terraform_labels", "vault_name"}, }, + { + Config: testAccNetappbackup_netappBackupFromVolumeSnapshot_update(context), + }, + { + ResourceName: "google_netapp_backup.test_backup", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "location", "name", "terraform_labels", "vault_name"}, + }, }, }) } @@ -92,3 +101,62 @@ resource "google_netapp_backup" "test_backup" { } `, context) } + +func testAccNetappbackup_netappBackupFromVolumeSnapshot_update(context map[string]interface{}) string { + return acctest.Nprintf(` +data "google_compute_network" "default" { + name = "%{network_name}" +} + +resource "google_netapp_storage_pool" "default" { + name = "tf-test-backup-pool%{random_suffix}" + location = "us-central1" + service_level = "PREMIUM" + capacity_gib = "2048" + network = data.google_compute_network.default.id +} + +resource "google_netapp_volume" "default" { + name = "tf-test-backup-volume%{random_suffix}" + location = google_netapp_storage_pool.default.location + capacity_gib = "100" + share_name = "tf-test-backup-volume%{random_suffix}" + storage_pool = google_netapp_storage_pool.default.name + protocols = ["NFSV3"] + deletion_policy = "FORCE" + backup_config { + backup_vault = google_netapp_backup_vault.default.id + } +} + +resource "google_netapp_backup_vault" "default" { + name = "tf-test-backup-vault%{random_suffix}" + location = google_netapp_storage_pool.default.location +} + +resource "google_netapp_volume_snapshot" "default" { + depends_on = [google_netapp_volume.default] + location = google_netapp_volume.default.location + volume_name = google_netapp_volume.default.name + description = "This is a test description" + name = "testvolumesnap%{random_suffix}" + labels = { + key= "test" + value= "snapshot" + } + } + +resource "google_netapp_backup" "test_backup" { + name = "tf-test-test-backup%{random_suffix}" + description = "This is a test backup" + source_volume = google_netapp_volume.default.id + location = google_netapp_backup_vault.default.location + vault_name = google_netapp_backup_vault.default.name + source_snapshot = google_netapp_volume_snapshot.default.id + labels = { + key= "test_update" + value= "backup_update" + } +} +`, context) +} From 8798992728b7c7b1c3b4ea7529d401f695897d8a Mon Sep 17 00:00:00 2001 From: Roopkamal Tyagi Date: Fri, 7 Jun 2024 05:25:24 +0000 Subject: [PATCH 5/5] Renaming resource file --- mmv1/products/netapp/{backup.yaml => Backup.yaml} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename mmv1/products/netapp/{backup.yaml => Backup.yaml} (99%) diff --git a/mmv1/products/netapp/backup.yaml b/mmv1/products/netapp/Backup.yaml similarity index 99% rename from mmv1/products/netapp/backup.yaml rename to mmv1/products/netapp/Backup.yaml index 45685fec52c4..3fe4d2693665 100644 --- a/mmv1/products/netapp/backup.yaml +++ b/mmv1/products/netapp/Backup.yaml @@ -1,4 +1,4 @@ -# Copyright 2023 Google Inc. +# Copyright 2024 Google Inc. # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at