From a958e3770be02ee481d891426b020a9599fa5cae Mon Sep 17 00:00:00 2001 From: roop2 <161707562+roop2@users.noreply.github.com> Date: Fri, 7 Jun 2024 21:33:59 +0530 Subject: [PATCH] Adding support for google_netapp_backup resource in netapp volumes (#10858) --- mmv1/products/netapp/Backup.yaml | 133 ++++++++++++++ .../terraform/examples/netapp_backup.tf.erb | 36 ++++ .../netapp/resource_netapp_backup_test.go | 162 ++++++++++++++++++ 3 files changed, 331 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..3fe4d2693665 --- /dev/null +++ b/mmv1/products/netapp/Backup.yaml @@ -0,0 +1,133 @@ +# 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 +# +# 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::String + name: 'state' + description: | + 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: | + 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::String + name: 'backupType' + description: | + 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' + 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..d12267b66a17 --- /dev/null +++ b/mmv1/third_party/terraform/services/netapp/resource_netapp_backup_test.go @@ -0,0 +1,162 @@ +// 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_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: 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"}, + }, + { + Config: testAccNetappbackup_netappBackupFromVolumeSnapshot_update(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}" + 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) +} + +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) +}