diff --git a/internal/services/storage/shim/shares.go b/internal/services/storage/shim/shares.go index 2d338010a5e3..b31297bb57a7 100644 --- a/internal/services/storage/shim/shares.go +++ b/internal/services/storage/shim/shares.go @@ -14,6 +14,7 @@ type StorageShareWrapper interface { UpdateACLs(ctx context.Context, resourceGroup, accountName, shareName string, acls []shares.SignedIdentifier) error UpdateMetaData(ctx context.Context, resourceGroup, accountName, shareName string, metaData map[string]string) error UpdateQuota(ctx context.Context, resourceGroup, accountName, shareName string, quotaGB int) error + UpdateTier(ctx context.Context, resourceGroup, accountName, shareName string, tier shares.AccessTier) error } type StorageShareProperties struct { @@ -21,4 +22,5 @@ type StorageShareProperties struct { MetaData map[string]string QuotaGB int EnabledProtocol shares.ShareProtocol + AccessTier *shares.AccessTier } diff --git a/internal/services/storage/shim/shares_data_plane.go b/internal/services/storage/shim/shares_data_plane.go index 1776ed965fec..cbb33651735a 100644 --- a/internal/services/storage/shim/shares_data_plane.go +++ b/internal/services/storage/shim/shares_data_plane.go @@ -110,6 +110,14 @@ func (w DataPlaneStorageShareWrapper) UpdateQuota(ctx context.Context, _, accoun return err } +func (w DataPlaneStorageShareWrapper) UpdateTier(ctx context.Context, _, accountname, shareName string, tier shares.AccessTier) error { + props := shares.ShareProperties{ + AccessTier: &tier, + } + _, err := w.client.SetProperties(ctx, accountname, shareName, props) + return err +} + func (w DataPlaneStorageShareWrapper) createRefreshFunc(ctx context.Context, accountName string, shareName string, input shares.CreateInput) pluginsdk.StateRefreshFunc { return func() (interface{}, string, error) { resp, err := w.client.Create(ctx, accountName, shareName, input) diff --git a/internal/services/storage/storage_share_resource.go b/internal/services/storage/storage_share_resource.go index fd5716f0c4eb..510f46bbdd14 100644 --- a/internal/services/storage/storage_share_resource.go +++ b/internal/services/storage/storage_share_resource.go @@ -120,6 +120,17 @@ func resourceStorageShare() *pluginsdk.Resource { Type: pluginsdk.TypeString, Computed: true, }, + + "access_tier": { + Type: pluginsdk.TypeString, + Optional: true, + Computed: true, + ValidateFunc: validation.StringInSlice( + []string{string(shares.HotAccessTier), + string(shares.CoolAccessTier), + string(shares.PremiumAccessTier), + string(shares.TransactionOptimizedAccessTier)}, false), + }, }, } } @@ -169,6 +180,11 @@ func resourceStorageShareCreate(d *pluginsdk.ResourceData, meta interface{}) err EnabledProtocol: shares.ShareProtocol(d.Get("enabled_protocol").(string)), } + if accessTier := d.Get("access_tier").(string); accessTier != "" { + tier := shares.AccessTier(accessTier) + input.AccessTier = &tier + } + if err := client.Create(ctx, account.ResourceGroup, accountName, shareName, input); err != nil { return fmt.Errorf("creating Share %q (Account %q / Resource Group %q): %+v", shareName, accountName, account.ResourceGroup, err) } @@ -222,6 +238,10 @@ func resourceStorageShareRead(d *pluginsdk.ResourceData, meta interface{}) error d.Set("url", id.ID()) d.Set("enabled_protocol", string(props.EnabledProtocol)) + if accessTier := props.AccessTier; accessTier != nil { + d.Set("access_tier", string(*accessTier)) + } + if err := d.Set("acl", flattenStorageShareACLs(props.ACLs)); err != nil { return fmt.Errorf("flattening `acl`: %+v", err) } @@ -296,6 +316,17 @@ func resourceStorageShareUpdate(d *pluginsdk.ResourceData, meta interface{}) err log.Printf("[DEBUG] Updated the ACL's for File Share %q (Storage Account %q)", id.Name, id.AccountName) } + if d.HasChange("access_tier") { + log.Printf("[DEBUG] Updating the Access Tier for File Share %q (Storage Account %q)", id.Name, id.AccountName) + + tier := shares.AccessTier(d.Get("access_tier").(string)) + if err := client.UpdateTier(ctx, account.ResourceGroup, id.AccountName, id.Name, tier); err != nil { + return fmt.Errorf("updating Access Tier for File Share %q (Storage Account %q): %s", id.Name, id.AccountName, err) + } + + log.Printf("[DEBUG] Updated the Access Tier for File Share %q (Storage Account %q)", id.Name, id.AccountName) + } + return resourceStorageShareRead(d, meta) } diff --git a/internal/services/storage/storage_share_resource_test.go b/internal/services/storage/storage_share_resource_test.go index f1b94a84ebe6..03213e282acf 100644 --- a/internal/services/storage/storage_share_resource_test.go +++ b/internal/services/storage/storage_share_resource_test.go @@ -11,6 +11,7 @@ import ( "github.com/hashicorp/terraform-provider-azurerm/internal/services/storage/parse" "github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk" "github.com/hashicorp/terraform-provider-azurerm/utils" + "github.com/tombuildsstuff/giovanni/storage/2020-08-04/file/shares" ) type StorageShareResource struct{} @@ -185,6 +186,42 @@ func TestAccStorageShare_largeQuota(t *testing.T) { }) } +func TestAccStorageShare_accessTier(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_storage_share", "test") + r := StorageShareResource{} + + data.ResourceTest(t, r, []acceptance.TestStep{ + { + Config: r.accessTier(data, string(shares.CoolAccessTier)), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep(), + { + Config: r.accessTier(data, string(shares.HotAccessTier)), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep(), + { + Config: r.accessTier(data, string(shares.PremiumAccessTier)), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep(), + { + Config: r.accessTier(data, string(shares.TransactionOptimizedAccessTier)), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep(), + }) +} + func TestAccStorageShare_nfsProtocol(t *testing.T) { data := acceptance.BuildTestData(t, "azurerm_storage_share", "test") r := StorageShareResource{} @@ -281,7 +318,7 @@ func (r StorageShareResource) basic(data acceptance.TestData) string { resource "azurerm_storage_share" "test" { name = "testshare%s" storage_account_name = azurerm_storage_account.test.name - quota = 1 + quota = 5 } `, template, data.RandomString) } @@ -294,7 +331,7 @@ func (r StorageShareResource) metaData(data acceptance.TestData) string { resource "azurerm_storage_share" "test" { name = "testshare%s" storage_account_name = azurerm_storage_account.test.name - quota = 1 + quota = 5 metadata = { hello = "world" @@ -311,7 +348,7 @@ func (r StorageShareResource) metaDataUpdated(data acceptance.TestData) string { resource "azurerm_storage_share" "test" { name = "testshare%s" storage_account_name = azurerm_storage_account.test.name - quota = 1 + quota = 5 metadata = { hello = "world" @@ -329,7 +366,7 @@ func (r StorageShareResource) acl(data acceptance.TestData) string { resource "azurerm_storage_share" "test" { name = "testshare%s" storage_account_name = azurerm_storage_account.test.name - quota = 1 + quota = 5 acl { id = "MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTI" @@ -352,7 +389,7 @@ func (r StorageShareResource) aclGhostedRecall(data acceptance.TestData) string resource "azurerm_storage_share" "test" { name = "testshare%s" storage_account_name = azurerm_storage_account.test.name - quota = 1 + quota = 5 acl { id = "GhostedRecall" @@ -372,7 +409,7 @@ func (r StorageShareResource) aclUpdated(data acceptance.TestData) string { resource "azurerm_storage_share" "test" { name = "testshare%s" storage_account_name = azurerm_storage_account.test.name - quota = 1 + quota = 5 acl { id = "AAAANDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTI" @@ -404,7 +441,7 @@ func (r StorageShareResource) requiresImport(data acceptance.TestData) string { resource "azurerm_storage_share" "import" { name = azurerm_storage_share.test.name storage_account_name = azurerm_storage_share.test.storage_account_name - quota = 1 + quota = 5 } `, template) } @@ -486,6 +523,35 @@ resource "azurerm_storage_share" "test" { `, data.RandomInteger, data.Locations.Primary, data.RandomString, data.RandomString) } +func (r StorageShareResource) accessTier(data acceptance.TestData, tier string) string { + return fmt.Sprintf(` +provider "azurerm" { + features {} +} + +resource "azurerm_resource_group" "test" { + name = "acctestRG-%d" + location = "%s" +} + +resource "azurerm_storage_account" "test" { + name = "acctestacc%s" + resource_group_name = azurerm_resource_group.test.name + location = azurerm_resource_group.test.location + account_tier = "Premium" + account_replication_type = "LRS" +} + +resource "azurerm_storage_share" "test" { + name = "testshare%s" + storage_account_name = azurerm_storage_account.test.name + quota = 100 + enabled_protocol = "NFS" + access_tier = "%s" +} +`, data.RandomInteger, data.Locations.Primary, data.RandomString, data.RandomString, tier) +} + func (r StorageShareResource) protocol(data acceptance.TestData, protocol string) string { return fmt.Sprintf(` provider "azurerm" { @@ -510,7 +576,7 @@ resource "azurerm_storage_share" "test" { name = "testshare%s" storage_account_name = azurerm_storage_account.test.name enabled_protocol = "%s" - quota = 1 + quota = 100 } `, data.RandomInteger, data.Locations.Primary, data.RandomString, data.RandomString, protocol) } diff --git a/website/docs/d/storage_share.html.markdown b/website/docs/d/storage_share.html.markdown index 393a0ed5b05b..40f24fad635e 100644 --- a/website/docs/d/storage_share.html.markdown +++ b/website/docs/d/storage_share.html.markdown @@ -37,6 +37,8 @@ The following arguments are supported: * `quota` - The quota of the File Share in GB. +* `access_tier` - The tier of the File Share. Can be one of `Hot`, `Cool`, `TransactionOptimized`, or `Premium`. + * `metadata` - A map of custom file share metadata. * `acl` - One or more acl blocks as defined below.