diff --git a/internal/services/storage/storage_account_resource.go b/internal/services/storage/storage_account_resource.go index e3acc874e647..9d72c386a4e4 100644 --- a/internal/services/storage/storage_account_resource.go +++ b/internal/services/storage/storage_account_resource.go @@ -64,17 +64,25 @@ type storageAccountServiceSupportLevel struct { supportStaticWebsite bool } -func resolveStorageAccountServiceSupportLevel(kind storage.Kind, tier storage.SkuTier) storageAccountServiceSupportLevel { +func resolveStorageAccountServiceSupportLevel(kind storage.Kind, tier storage.SkuTier, replicationType string) storageAccountServiceSupportLevel { // FileStorage doesn't support blob supportBlob := kind != storage.KindFileStorage // Queue is only supported for Storage and StorageV2, in Standard sku tier. - supportQueue := tier == storage.SkuTierStandard && slices.Contains([]storage.Kind{storage.KindStorage, storage.KindStorageV2}, kind) + supportQueue := tier == storage.SkuTierStandard && (kind == storage.KindStorageV2 || + (kind == storage.KindStorage && + // Per local test, only LRS/GRS/RAGRS Storage V1 accounts support queue endpoint. + // GZRS and RAGZRS is invalid, while ZRS is valid but has no queue endpoint. + slices.Contains([]string{"LRS", "GRS", "RAGRS"}, replicationType))) // File share is only supported for StorageV2 and FileStorage. // See: https://docs.microsoft.com/en-us/azure/storage/files/storage-files-planning#management-concepts // Per test, the StorageV2 with Premium sku tier also doesn't support file share. - supportShare := kind == storage.KindFileStorage || (slices.Contains([]storage.Kind{storage.KindStorage, storage.KindStorageV2}, kind) && tier != storage.SkuTierPremium) + supportShare := kind == storage.KindFileStorage || (tier != storage.SkuTierPremium && (kind == storage.KindStorageV2 || + (kind == storage.KindStorage && + // Per local test, only LRS/GRS/RAGRS Storage V1 accounts support file endpoint. + // GZRS and RAGZRS is invalid, while ZRS is valid but has no file endpoint. + slices.Contains([]string{"LRS", "GRS", "RAGRS"}, replicationType)))) // Static Website is only supported for StorageV2 (not for Storage(v1)) and BlockBlobStorage supportStaticWebSite := kind == storage.KindStorageV2 || kind == storage.KindBlockBlobStorage @@ -1544,7 +1552,7 @@ func resourceStorageAccountCreate(d *pluginsdk.ResourceData, meta interface{}) e return fmt.Errorf("populating cache for %s: %+v", id, err) } - supportLevel := resolveStorageAccountServiceSupportLevel(accountKind, accountTier) + supportLevel := resolveStorageAccountServiceSupportLevel(accountKind, accountTier, replicationType) if val, ok := d.GetOk("blob_properties"); ok { if !supportLevel.supportBlob { @@ -1896,7 +1904,7 @@ func resourceStorageAccountUpdate(d *pluginsdk.ResourceData, meta interface{}) e } // Followings are updates to the sub-services - supportLevel := resolveStorageAccountServiceSupportLevel(accountKind, accountTier) + supportLevel := resolveStorageAccountServiceSupportLevel(accountKind, accountTier, replicationType) if d.HasChange("blob_properties") { if !supportLevel.supportBlob { @@ -2257,7 +2265,7 @@ func resourceStorageAccountRead(d *pluginsdk.ResourceData, meta interface{}) err if resp.Sku != nil { tier = resp.Sku.Tier } - supportLevel := resolveStorageAccountServiceSupportLevel(resp.Kind, tier) + supportLevel := resolveStorageAccountServiceSupportLevel(resp.Kind, tier, d.Get("account_replication_type").(string)) if supportLevel.supportBlob { blobClient := storageClient.BlobServicesClient diff --git a/internal/services/storage/storage_account_resource_test.go b/internal/services/storage/storage_account_resource_test.go index 4c17cbab8efb..80c039c6b58c 100644 --- a/internal/services/storage/storage_account_resource_test.go +++ b/internal/services/storage/storage_account_resource_test.go @@ -1626,13 +1626,13 @@ func TestAccStorageAccount_StorageV1_blobProperties(t *testing.T) { }) } -func TestAccStorageAccount_StorageV1_queueProperties(t *testing.T) { +func TestAccStorageAccount_StorageV1_queuePropertiesLRS(t *testing.T) { data := acceptance.BuildTestData(t, "azurerm_storage_account", "test") r := StorageAccountResource{} data.ResourceTest(t, r, []acceptance.TestStep{ { - Config: r.storageV1QueueProperties(data), + Config: r.storageV1QueueProperties(data, "LRS"), Check: acceptance.ComposeTestCheckFunc( check.That(data.ResourceName).ExistsInAzure(r), ), @@ -1641,13 +1641,13 @@ func TestAccStorageAccount_StorageV1_queueProperties(t *testing.T) { }) } -func TestAccStorageAccount_StorageV1_shareProperties(t *testing.T) { +func TestAccStorageAccount_StorageV1_queuePropertiesGRS(t *testing.T) { data := acceptance.BuildTestData(t, "azurerm_storage_account", "test") r := StorageAccountResource{} data.ResourceTest(t, r, []acceptance.TestStep{ { - Config: r.storageV1ShareProperties(data), + Config: r.storageV1QueueProperties(data, "GRS"), Check: acceptance.ComposeTestCheckFunc( check.That(data.ResourceName).ExistsInAzure(r), ), @@ -1655,6 +1655,67 @@ func TestAccStorageAccount_StorageV1_shareProperties(t *testing.T) { data.ImportStep(), }) } + +func TestAccStorageAccount_StorageV1_queuePropertiesRAGRS(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_storage_account", "test") + r := StorageAccountResource{} + + data.ResourceTest(t, r, []acceptance.TestStep{ + { + Config: r.storageV1QueueProperties(data, "RAGRS"), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep(), + }) +} + +func TestAccStorageAccount_StorageV1_sharePropertiesLRS(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_storage_account", "test") + r := StorageAccountResource{} + + data.ResourceTest(t, r, []acceptance.TestStep{ + { + Config: r.storageV1ShareProperties(data, "LRS"), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep(), + }) +} + +func TestAccStorageAccount_StorageV1_sharePropertiesGRS(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_storage_account", "test") + r := StorageAccountResource{} + + data.ResourceTest(t, r, []acceptance.TestStep{ + { + Config: r.storageV1ShareProperties(data, "GRS"), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep(), + }) +} + +func TestAccStorageAccount_StorageV1_sharePropertiesRAGRS(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_storage_account", "test") + r := StorageAccountResource{} + + data.ResourceTest(t, r, []acceptance.TestStep{ + { + Config: r.storageV1ShareProperties(data, "RAGRS"), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep(), + }) +} + func (r StorageAccountResource) Exists(ctx context.Context, client *clients.Client, state *pluginsdk.InstanceState) (*bool, error) { id, err := commonids.ParseStorageAccountID(state.ID) if err != nil { @@ -4788,7 +4849,7 @@ resource "azurerm_storage_account" "test" { `, data.RandomInteger, data.Locations.Primary, data.RandomString) } -func (r StorageAccountResource) storageV1QueueProperties(data acceptance.TestData) string { +func (r StorageAccountResource) storageV1QueueProperties(data acceptance.TestData, repl string) string { return fmt.Sprintf(` provider "azurerm" { features {} @@ -4806,7 +4867,7 @@ resource "azurerm_storage_account" "test" { location = azurerm_resource_group.test.location account_kind = "Storage" account_tier = "Standard" - account_replication_type = "LRS" + account_replication_type = "%s" queue_properties { cors_rule { @@ -4838,10 +4899,10 @@ resource "azurerm_storage_account" "test" { } } } -`, data.RandomInteger, data.Locations.Primary, data.RandomString) +`, data.RandomInteger, data.Locations.Primary, data.RandomString, repl) } -func (r StorageAccountResource) storageV1ShareProperties(data acceptance.TestData) string { +func (r StorageAccountResource) storageV1ShareProperties(data acceptance.TestData, repl string) string { return fmt.Sprintf(` provider "azurerm" { features {} @@ -4859,7 +4920,7 @@ resource "azurerm_storage_account" "test" { location = azurerm_resource_group.test.location account_kind = "Storage" account_tier = "Standard" - account_replication_type = "LRS" + account_replication_type = "%s" share_properties { cors_rule { @@ -4881,5 +4942,5 @@ resource "azurerm_storage_account" "test" { } } } -`, data.RandomInteger, data.Locations.Primary, data.RandomString) +`, data.RandomInteger, data.Locations.Primary, data.RandomString, repl) }