diff --git a/internal/services/dataprotection/data_protection_backup_vault_resource.go b/internal/services/dataprotection/data_protection_backup_vault_resource.go index 2cc219592ba6..144dcc7cacfb 100644 --- a/internal/services/dataprotection/data_protection_backup_vault_resource.go +++ b/internal/services/dataprotection/data_protection_backup_vault_resource.go @@ -4,6 +4,7 @@ package dataprotection import ( + "context" "fmt" "log" "regexp" @@ -72,8 +73,28 @@ func resourceDataProtectionBackupVault() *pluginsdk.Resource { "identity": commonschema.SystemAssignedIdentityOptional(), + "retention_duration_in_days": { + Type: pluginsdk.TypeFloat, + Optional: true, + Default: 14, + ValidateFunc: validation.FloatBetween(14, 180), + }, + + "soft_delete": { + Type: pluginsdk.TypeString, + Optional: true, + Default: backupvaults.SoftDeleteStateOn, + ValidateFunc: validation.StringInSlice(backupvaults.PossibleValuesForSoftDeleteState(), false), + }, + "tags": tags.Schema(), }, + + CustomizeDiff: pluginsdk.CustomDiffWithAll( + pluginsdk.ForceNewIfChange("soft_delete", func(ctx context.Context, old, new, meta interface{}) bool { + return old.(string) == string(backupvaults.SoftDeleteStateAlwaysOn) && new.(string) != string(backupvaults.SoftDeleteStateAlwaysOn) + }), + ), } // Confirmed with the service team that `SnapshotStore` has been replaced with `OperationalStore`. @@ -144,10 +165,20 @@ func resourceDataProtectionBackupVaultCreateUpdate(d *pluginsdk.ResourceData, me Type: &storageSettingType, }, }, + SecuritySettings: &backupvaults.SecuritySettings{ + SoftDeleteSettings: &backupvaults.SoftDeleteSettings{ + State: pointer.To(backupvaults.SoftDeleteState(d.Get("soft_delete").(string))), + }, + }, }, Identity: expandedIdentity, Tags: expandTags(d.Get("tags").(map[string]interface{})), } + + if v, ok := d.GetOk("retention_duration_in_days"); ok { + parameters.Properties.SecuritySettings.SoftDeleteSettings.RetentionDurationInDays = pointer.To(v.(float64)) + } + err = client.CreateOrUpdateThenPoll(ctx, id, parameters) if err != nil { return fmt.Errorf("creating DataProtection BackupVault (%q): %+v", id, err) @@ -186,6 +217,12 @@ func resourceDataProtectionBackupVaultRead(d *pluginsdk.ResourceData, meta inter d.Set("datastore_type", string(pointer.From((props.StorageSettings)[0].DatastoreType))) d.Set("redundancy", string(pointer.From((props.StorageSettings)[0].Type))) } + if securitySetting := model.Properties.SecuritySettings; securitySetting != nil { + if softDelete := securitySetting.SoftDeleteSettings; softDelete != nil { + d.Set("soft_delete", string(pointer.From(softDelete.State))) + d.Set("retention_duration_in_days", pointer.From(softDelete.RetentionDurationInDays)) + } + } if err = d.Set("identity", flattenBackupVaultDppIdentityDetails(model.Identity)); err != nil { return fmt.Errorf("setting `identity`: %+v", err) diff --git a/internal/services/dataprotection/data_protection_backup_vault_resource_test.go b/internal/services/dataprotection/data_protection_backup_vault_resource_test.go index f21e88fd4da3..0cfc4287eb56 100644 --- a/internal/services/dataprotection/data_protection_backup_vault_resource_test.go +++ b/internal/services/dataprotection/data_protection_backup_vault_resource_test.go @@ -93,6 +93,13 @@ func TestAccDataProtectionBackupVault_update(t *testing.T) { ), }, data.ImportStep(), + { + Config: r.completeUpdate(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep(), { Config: r.basic(data), Check: acceptance.ComposeTestCheckFunc( @@ -200,7 +207,31 @@ resource "azurerm_data_protection_backup_vault" "test" { identity { type = "SystemAssigned" } + soft_delete = "Off" + retention_duration_in_days = 14 + tags = { + ENV = "Test" + } +} +`, template, data.RandomInteger) +} + +func (r DataProtectionBackupVaultResource) completeUpdate(data acceptance.TestData) string { + template := r.template(data) + return fmt.Sprintf(` +%s +resource "azurerm_data_protection_backup_vault" "test" { + name = "acctest-bv-%d" + resource_group_name = azurerm_resource_group.test.name + location = azurerm_resource_group.test.location + datastore_type = "VaultStore" + redundancy = "LocallyRedundant" + identity { + type = "SystemAssigned" + } + soft_delete = "On" + retention_duration_in_days = 15 tags = { ENV = "Test" } @@ -219,7 +250,6 @@ resource "azurerm_data_protection_backup_vault" "test" { location = azurerm_resource_group.test.location datastore_type = "VaultStore" redundancy = "LocallyRedundant" - tags = { ENV = "Test" } diff --git a/website/docs/r/data_protection_backup_vault.html.markdown b/website/docs/r/data_protection_backup_vault.html.markdown index bc74db02c63e..7ec3d0373c8b 100644 --- a/website/docs/r/data_protection_backup_vault.html.markdown +++ b/website/docs/r/data_protection_backup_vault.html.markdown @@ -47,6 +47,14 @@ The following arguments are supported: * `identity` - (Optional) An `identity` block as defined below. +* `retention_duration_in_days` - (Optional) The soft delete retention duration for this Backup Vault. Possible values are between `14` and `180`. Defaults to `14`. + +-> **Note:** The `retention_duration_in_days` is the number of days for which deleted data is retained before being permanently deleted. Retention period till 14 days are free of cost, however, retention beyond 14 days may incur additional charges. The `retention_duration_in_days` is required when the `soft_delete` is set to `On`. + +* `soft_delete` - (Optional) The state of soft delete for this Backup Vault. Possible values are `AlwaysOn`, `Off` and `On`. Defaults to `On`. + +-> **Note:** Once the `soft_delete` is set to `AlwaysOn`, the setting cannot be changed. + * `tags` - (Optional) A mapping of tags which should be assigned to the Backup Vault. ---