diff --git a/internal/services/storage/storage_account_resource.go b/internal/services/storage/storage_account_resource.go index d93401053533..6755eb7525a1 100644 --- a/internal/services/storage/storage_account_resource.go +++ b/internal/services/storage/storage_account_resource.go @@ -1307,7 +1307,10 @@ func resourceStorageAccountCreate(d *pluginsdk.ResourceData, meta interface{}) e } blobClient := meta.(*clients.Client).Storage.BlobServicesClient - blobProperties := expandBlobProperties(val.([]interface{})) + blobProperties, err := expandBlobProperties(val.([]interface{})) + if err != nil { + return err + } // last_access_time_enabled and container_delete_retention_policy are not supported in USGov // Fix issue https://github.com/hashicorp/terraform-provider-azurerm/issues/11772 @@ -1774,7 +1777,10 @@ func resourceStorageAccountUpdate(d *pluginsdk.ResourceData, meta interface{}) e } blobClient := meta.(*clients.Client).Storage.BlobServicesClient - blobProperties := expandBlobProperties(d.Get("blob_properties").([]interface{})) + blobProperties, err := expandBlobProperties(d.Get("blob_properties").([]interface{})) + if err != nil { + return err + } // last_access_time_enabled and container_delete_retention_policy are not supported in USGov // Fix issue https://github.com/hashicorp/terraform-provider-azurerm/issues/11772 @@ -2579,7 +2585,7 @@ func expandStorageAccountPrivateLinkAccess(inputs []interface{}, tenantId string return &privateLinkAccess } -func expandBlobProperties(input []interface{}) *storage.BlobServiceProperties { +func expandBlobProperties(input []interface{}) (*storage.BlobServiceProperties, error) { props := storage.BlobServiceProperties{ BlobServicePropertiesProperties: &storage.BlobServicePropertiesProperties{ Cors: &storage.CorsRules{ @@ -2596,7 +2602,7 @@ func expandBlobProperties(input []interface{}) *storage.BlobServiceProperties { } if len(input) == 0 || input[0] == nil { - return &props + return &props, nil } v := input[0].(map[string]interface{}) @@ -2624,7 +2630,18 @@ func expandBlobProperties(input []interface{}) *storage.BlobServiceProperties { props.DefaultServiceVersion = utils.String(version) } - return &props + // Sanity check for the prerequisites of restore_policy + // Ref: https://learn.microsoft.com/en-us/azure/storage/blobs/point-in-time-restore-overview#prerequisites-for-point-in-time-restore + if p := props.BlobServicePropertiesProperties.RestorePolicy; p != nil && p.Enabled != nil && *p.Enabled { + if props.ChangeFeed == nil || props.ChangeFeed.Enabled == nil || !*props.ChangeFeed.Enabled { + return nil, fmt.Errorf("`change_feed_enabled` must be `true` when `restore_policy` is set") + } + if props.IsVersioningEnabled == nil || !*props.IsVersioningEnabled { + return nil, fmt.Errorf("`versioning_enabled` must be `true` when `restore_policy` is set") + } + } + + return &props, nil } func expandBlobPropertiesDeleteRetentionPolicy(input []interface{}) *storage.DeleteRetentionPolicy { diff --git a/internal/services/storage/storage_account_resource_test.go b/internal/services/storage/storage_account_resource_test.go index b4215895a593..bc9e603526ff 100644 --- a/internal/services/storage/storage_account_resource_test.go +++ b/internal/services/storage/storage_account_resource_test.go @@ -600,6 +600,13 @@ func TestAccStorageAccount_blobProperties(t *testing.T) { r := StorageAccountResource{} data.ResourceTest(t, r, []acceptance.TestStep{ + { + Config: r.restorePolicyMinimal(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep(), { Config: r.blobProperties(data), Check: acceptance.ComposeTestCheckFunc( @@ -2507,6 +2514,39 @@ resource "azurerm_storage_account" "test" { `, data.RandomInteger, data.Locations.Primary, data.RandomString) } +func (r StorageAccountResource) restorePolicyMinimal(data acceptance.TestData) string { + return fmt.Sprintf(` +provider "azurerm" { + features {} +} + +resource "azurerm_resource_group" "test" { + name = "acctestAzureRMSA-%d" + location = "%s" +} + +resource "azurerm_storage_account" "test" { + name = "unlikely23exst2acct%s" + resource_group_name = azurerm_resource_group.test.name + + location = azurerm_resource_group.test.location + account_tier = "Standard" + account_replication_type = "LRS" + + blob_properties { + delete_retention_policy {} + + restore_policy { + days = 6 + } + + versioning_enabled = true + change_feed_enabled = true + } +} +`, data.RandomInteger, data.Locations.Primary, data.RandomString) +} + func (r StorageAccountResource) blobPropertiesContainerAndLastAccessTimeDisabled(data acceptance.TestData) string { return fmt.Sprintf(` provider "azurerm" { diff --git a/website/docs/r/storage_account.html.markdown b/website/docs/r/storage_account.html.markdown index a1557b443ee5..248a465c81fa 100644 --- a/website/docs/r/storage_account.html.markdown +++ b/website/docs/r/storage_account.html.markdown @@ -180,7 +180,7 @@ A `blob_properties` block supports the following: * `delete_retention_policy` - (Optional) A `delete_retention_policy` block as defined below. -* `restore_policy` - (Optional) A `restore_policy` block as defined below. This must be used together with `delete_retention_policy` set and `versioning_enabled` set to `true`. +* `restore_policy` - (Optional) A `restore_policy` block as defined below. This must be used together with `delete_retention_policy` set, `versioning_enabled` and `change_feed_enabled` set to `true`. * `versioning_enabled` - (Optional) Is versioning enabled? Default to `false`.