diff --git a/internal/services/dataprotection/data_protection_backup_vault_resource.go b/internal/services/dataprotection/data_protection_backup_vault_resource.go index 02a1299cea7a..20d3912933f8 100644 --- a/internal/services/dataprotection/data_protection_backup_vault_resource.go +++ b/internal/services/dataprotection/data_protection_backup_vault_resource.go @@ -26,7 +26,7 @@ import ( ) func resourceDataProtectionBackupVault() *pluginsdk.Resource { - resource := &pluginsdk.Resource{ + return &pluginsdk.Resource{ Create: resourceDataProtectionBackupVaultCreateUpdate, Read: resourceDataProtectionBackupVaultRead, Update: resourceDataProtectionBackupVaultCreateUpdate, @@ -86,8 +86,6 @@ func resourceDataProtectionBackupVault() *pluginsdk.Resource { Optional: true, }, - "identity": commonschema.SystemAssignedIdentityOptional(), - "retention_duration_in_days": { Type: pluginsdk.TypeFloat, Optional: true, @@ -102,19 +100,34 @@ func resourceDataProtectionBackupVault() *pluginsdk.Resource { ValidateFunc: validation.StringInSlice(backupvaults.PossibleValuesForSoftDeleteState(), false), }, + "immutability": { + Type: pluginsdk.TypeString, + Optional: true, + Default: backupvaults.ImmutabilityStateDisabled, + ValidateFunc: validation.StringInSlice(backupvaults.PossibleValuesForImmutabilityState(), false), + }, + + "identity": commonschema.SystemAssignedIdentityOptional(), + "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) - }), - // Once `cross_region_restore_enabled` is enabled it cannot be disabled. + // Once `immutability` is enabled it cannot be disabled. pluginsdk.ForceNewIfChange("cross_region_restore_enabled", func(ctx context.Context, old, new, meta interface{}) bool { return old.(bool) && new.(bool) != old.(bool) }), + // Once `cross_region_restore_enabled` is enabled it cannot be disabled. + pluginsdk.ForceNewIfChange("immutability", func(ctx context.Context, old, new, meta interface{}) bool { + return old.(string) == string(backupvaults.ImmutabilityStateLocked) && new.(string) != string(backupvaults.ImmutabilityStateLocked) + }), + + pluginsdk.ForceNewIfChange("soft_delete", func(ctx context.Context, old, new, meta interface{}) bool { + return old.(string) == string(backupvaults.SoftDeleteStateAlwaysOn) && new.(string) != string(backupvaults.SoftDeleteStateAlwaysOn) + }), + pluginsdk.CustomizeDiffShim(func(ctx context.Context, d *pluginsdk.ResourceDiff, v interface{}) error { redundancy := d.Get("redundancy").(string) crossRegionRestore := d.GetRawConfig().AsValueMap()["cross_region_restore_enabled"] @@ -126,8 +139,6 @@ func resourceDataProtectionBackupVault() *pluginsdk.Resource { }), ), } - - return resource } func resourceDataProtectionBackupVaultCreateUpdate(d *pluginsdk.ResourceData, meta interface{}) error { @@ -158,22 +169,22 @@ func resourceDataProtectionBackupVaultCreateUpdate(d *pluginsdk.ResourceData, me return fmt.Errorf("expanding `identity`: %+v", err) } - datastoreType := backupvaults.StorageSettingStoreTypes(d.Get("datastore_type").(string)) - storageSettingType := backupvaults.StorageSettingTypes(d.Get("redundancy").(string)) - parameters := backupvaults.BackupVaultResource{ Location: pointer.To(location.Normalize(d.Get("location").(string))), Properties: backupvaults.BackupVault{ StorageSettings: []backupvaults.StorageSetting{ { - DatastoreType: &datastoreType, - Type: &storageSettingType, + DatastoreType: pointer.To(backupvaults.StorageSettingStoreTypes(d.Get("datastore_type").(string))), + Type: pointer.To(backupvaults.StorageSettingTypes(d.Get("redundancy").(string))), }, }, SecuritySettings: &backupvaults.SecuritySettings{ SoftDeleteSettings: &backupvaults.SoftDeleteSettings{ State: pointer.To(backupvaults.SoftDeleteState(d.Get("soft_delete").(string))), }, + ImmutabilitySettings: &backupvaults.ImmutabilitySettings{ + State: pointer.To(backupvaults.ImmutabilityState(d.Get("immutability").(string))), + }, }, }, Identity: expandedIdentity, @@ -229,16 +240,26 @@ func resourceDataProtectionBackupVaultRead(d *pluginsdk.ResourceData, meta inter if model := resp.Model; model != nil { d.Set("location", location.NormalizeNilable(model.Location)) props := model.Properties + if len(props.StorageSettings) > 0 { d.Set("datastore_type", string(pointer.From((props.StorageSettings)[0].DatastoreType))) d.Set("redundancy", string(pointer.From((props.StorageSettings)[0].Type))) } + + immutability := backupvaults.ImmutabilityStateDisabled if securitySetting := model.Properties.SecuritySettings; securitySetting != nil { + if immutabilitySettings := securitySetting.ImmutabilitySettings; immutabilitySettings != nil { + if immutabilitySettings.State != nil { + immutability = *immutabilitySettings.State + } + } 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)) } } + d.Set("immutability", string(immutability)) + crossRegionStoreEnabled := false if featureSetting := model.Properties.FeatureSettings; featureSetting != nil { if crossRegionRestore := featureSetting.CrossRegionRestoreSettings; crossRegionRestore != nil { @@ -247,7 +268,6 @@ func resourceDataProtectionBackupVaultRead(d *pluginsdk.ResourceData, meta inter } } } - d.Set("cross_region_restore_enabled", crossRegionStoreEnabled) if err = d.Set("identity", flattenBackupVaultDppIdentityDetails(model.Identity)); err != nil { 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 061fde32fa7c..fee233165c12 100644 --- a/internal/services/dataprotection/data_protection_backup_vault_resource_test.go +++ b/internal/services/dataprotection/data_protection_backup_vault_resource_test.go @@ -241,11 +241,15 @@ resource "azurerm_data_protection_backup_vault" "test" { location = azurerm_resource_group.test.location datastore_type = "VaultStore" redundancy = "LocallyRedundant" + identity { type = "SystemAssigned" } + + immutability = "Disabled" soft_delete = "Off" retention_duration_in_days = 14 + tags = { ENV = "Test" } @@ -264,11 +268,15 @@ resource "azurerm_data_protection_backup_vault" "test" { location = azurerm_resource_group.test.location datastore_type = "VaultStore" redundancy = "LocallyRedundant" + identity { type = "SystemAssigned" } + + immutability = "Locked" soft_delete = "On" retention_duration_in_days = 15 + tags = { ENV = "Test" } @@ -287,6 +295,7 @@ 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 df58c302a2b3..2ed4d8c65404 100644 --- a/website/docs/r/data_protection_backup_vault.html.markdown +++ b/website/docs/r/data_protection_backup_vault.html.markdown @@ -55,7 +55,9 @@ The following arguments are supported: -> **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`. +* `immutability` - (Optional) The state of immutability for this Backup Vault. Possible values are `Disabled`, `Locked`, and `Unlocked`. Defaults to `Disabled`. Changing this from `Locked` to anything else forces a new Backup Vault to be created. + +* `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.