Skip to content

Commit

Permalink
azurerm_storage_account - For Storage kind account, avoid setting…
Browse files Browse the repository at this point in the history
… some unsupported blob properties (#23288)

* `azurerm_storage_account` - For `Storage` kind account, avoid setting some unsupported blob properties

* Explicitly mention Storage v1
  • Loading branch information
magodo authored Sep 18, 2023
1 parent bcd4057 commit f50e3ca
Show file tree
Hide file tree
Showing 3 changed files with 130 additions and 23 deletions.
79 changes: 56 additions & 23 deletions internal/services/storage/storage_account_resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -1324,7 +1324,7 @@ func resourceStorageAccountCreate(d *pluginsdk.ResourceData, meta interface{}) e
}
blobClient := meta.(*clients.Client).Storage.BlobServicesClient

blobProperties, err := expandBlobProperties(val.([]interface{}))
blobProperties, err := expandBlobProperties(storage.Kind(accountKind), val.([]interface{}))
if err != nil {
return err
}
Expand Down Expand Up @@ -1794,7 +1794,7 @@ func resourceStorageAccountUpdate(d *pluginsdk.ResourceData, meta interface{}) e
}

blobClient := meta.(*clients.Client).Storage.BlobServicesClient
blobProperties, err := expandBlobProperties(d.Get("blob_properties").([]interface{}))
blobProperties, err := expandBlobProperties(storage.Kind(accountKind), d.Get("blob_properties").([]interface{}))
if err != nil {
return err
}
Expand Down Expand Up @@ -2611,25 +2611,33 @@ func expandStorageAccountPrivateLinkAccess(inputs []interface{}, tenantId string
return &privateLinkAccess
}

func expandBlobProperties(input []interface{}) (*storage.BlobServiceProperties, error) {
func expandBlobProperties(kind storage.Kind, input []interface{}) (*storage.BlobServiceProperties, error) {
props := storage.BlobServiceProperties{
BlobServicePropertiesProperties: &storage.BlobServicePropertiesProperties{
Cors: &storage.CorsRules{
CorsRules: &[]storage.CorsRule{},
},
IsVersioningEnabled: utils.Bool(false),
ChangeFeed: &storage.ChangeFeed{
Enabled: utils.Bool(false),
},
DeleteRetentionPolicy: &storage.DeleteRetentionPolicy{
Enabled: utils.Bool(false),
},
LastAccessTimeTrackingPolicy: &storage.LastAccessTimeTrackingPolicy{
Enable: utils.Bool(false),
},
},
}

// `Storage` (v1) kind doesn't support:
// - LastAccessTimeTrackingPolicy: Confirmed by SRP.
// - ChangeFeed: See https://learn.microsoft.com/en-us/azure/storage/blobs/storage-blob-change-feed?tabs=azure-portal#enable-and-disable-the-change-feed.
// - Versioning: See https://learn.microsoft.com/en-us/azure/storage/blobs/versioning-overview#how-blob-versioning-works
// - Restore Policy: See https://learn.microsoft.com/en-us/azure/storage/blobs/point-in-time-restore-overview#prerequisites-for-point-in-time-restore
if kind != storage.KindStorage {
props.LastAccessTimeTrackingPolicy = &storage.LastAccessTimeTrackingPolicy{
Enable: utils.Bool(false),
}
props.ChangeFeed = &storage.ChangeFeed{
Enabled: utils.Bool(false),
}
props.IsVersioningEnabled = utils.Bool(false)
}

if len(input) == 0 || input[0] == nil {
return &props, nil
}
Expand All @@ -2642,28 +2650,53 @@ func expandBlobProperties(input []interface{}) (*storage.BlobServiceProperties,
containerDeletePolicyRaw := v["container_delete_retention_policy"].([]interface{})
props.BlobServicePropertiesProperties.ContainerDeleteRetentionPolicy = expandBlobPropertiesDeleteRetentionPolicy(containerDeletePolicyRaw)

restorePolicyRaw := v["restore_policy"].([]interface{})
props.BlobServicePropertiesProperties.RestorePolicy = expandBlobPropertiesRestorePolicy(restorePolicyRaw)

corsRaw := v["cors_rule"].([]interface{})
props.BlobServicePropertiesProperties.Cors = expandBlobPropertiesCors(corsRaw)

props.IsVersioningEnabled = utils.Bool(v["versioning_enabled"].(bool))

props.ChangeFeed = &storage.ChangeFeed{
Enabled: utils.Bool(v["change_feed_enabled"].(bool)),
}

if v := v["change_feed_retention_in_days"].(int); v != 0 {
props.ChangeFeed.RetentionInDays = utils.Int32((int32)(v))
}

if version, ok := v["default_service_version"].(string); ok && version != "" {
props.DefaultServiceVersion = utils.String(version)
}

props.LastAccessTimeTrackingPolicy = &storage.LastAccessTimeTrackingPolicy{
Enable: utils.Bool(v["last_access_time_enabled"].(bool)),
// `Storage` (v1) kind doesn't support:
// - LastAccessTimeTrackingPolicy
// - ChangeFeed
// - Versioning
// - RestorePolicy
lastAccessTimeEnabled := v["last_access_time_enabled"].(bool)
changeFeedEnabled := v["change_feed_enabled"].(bool)
changeFeedRetentionInDays := v["change_feed_retention_in_days"].(int)
restorePolicyRaw := v["restore_policy"].([]interface{})
versioningEnabled := v["versioning_enabled"].(bool)
if kind != storage.KindStorage {
props.BlobServicePropertiesProperties.LastAccessTimeTrackingPolicy = &storage.LastAccessTimeTrackingPolicy{
Enable: utils.Bool(lastAccessTimeEnabled),
}
props.BlobServicePropertiesProperties.ChangeFeed = &storage.ChangeFeed{
Enabled: utils.Bool(changeFeedEnabled),
}
if changeFeedRetentionInDays != 0 {
props.BlobServicePropertiesProperties.ChangeFeed.RetentionInDays = utils.Int32(int32(changeFeedRetentionInDays))
}
props.BlobServicePropertiesProperties.RestorePolicy = expandBlobPropertiesRestorePolicy(restorePolicyRaw)
props.BlobServicePropertiesProperties.IsVersioningEnabled = &versioningEnabled
} else {
if lastAccessTimeEnabled {
return nil, fmt.Errorf("`last_access_time_enabled` can not be configured when `kind` is set to `Storage` (v1)")
}
if changeFeedEnabled {
return nil, fmt.Errorf("`change_feed_enabled` can not be configured when `kind` is set to `Storage` (v1)")
}
if changeFeedRetentionInDays != 0 {
return nil, fmt.Errorf("`change_feed_retention_in_days` can not be configured when `kind` is set to `Storage` (v1)")
}
if len(restorePolicyRaw) != 0 {
return nil, fmt.Errorf("`restore_policy` can not be configured when `kind` is set to `Storage` (v1)")
}
if versioningEnabled {
return nil, fmt.Errorf("`versioning_enabled` can not be configured when `kind` is set to `Storage` (v1)")
}
}

// Sanity check for the prerequisites of restore_policy
Expand Down
64 changes: 64 additions & 0 deletions internal/services/storage/storage_account_resource_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -695,6 +695,21 @@ func TestAccStorageAccount_blobPropertiesEmptyAllowedExposedHeaders(t *testing.T
})
}

func TestAccStorageAccount_blobProperties_kindStorageNotSupportLastAccessTimeEnabled(t *testing.T) {
data := acceptance.BuildTestData(t, "azurerm_storage_account", "test")
r := StorageAccountResource{}

data.ResourceTest(t, r, []acceptance.TestStep{
{
Config: r.blobPropertiesStorageKindNotSupportLastAccessTimeEnabled(data),
Check: acceptance.ComposeTestCheckFunc(
check.That(data.ResourceName).ExistsInAzure(r),
),
},
data.ImportStep(),
})
}

func TestAccStorageAccount_queueProperties(t *testing.T) {
data := acceptance.BuildTestData(t, "azurerm_storage_account", "test")
r := StorageAccountResource{}
Expand Down Expand Up @@ -4463,3 +4478,52 @@ resource "azurerm_storage_account" "test" {
}
`, data.RandomInteger, data.Locations.Primary, data.RandomString)
}

func (r StorageAccountResource) blobPropertiesStorageKindNotSupportLastAccessTimeEnabled(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_kind = "Storage"
account_tier = "Standard"
account_replication_type = "LRS"
blob_properties {
cors_rule {
allowed_origins = ["http://www.example.com"]
exposed_headers = ["x-tempo-*"]
allowed_headers = ["x-tempo-*"]
allowed_methods = ["GET", "PUT", "PATCH"]
max_age_in_seconds = "500"
}
delete_retention_policy {
days = 300
}
default_service_version = "2019-07-07"
container_delete_retention_policy {
days = 7
}
# Following properties are not supported for "Storage" (v1) kind
last_access_time_enabled = false
change_feed_enabled = false
versioning_enabled = false
# change_feed_retention_in_days
# restore_policy
}
}
`, data.RandomInteger, data.Locations.Primary, data.RandomString)
}
10 changes: 10 additions & 0 deletions website/docs/r/storage_account.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -183,16 +183,26 @@ A `blob_properties` block supports the following:

* `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`.

-> **NOTE:** This field cannot be configured when `kind` is set to `Storage` (V1).

* `versioning_enabled` - (Optional) Is versioning enabled? Default to `false`.

-> **NOTE:** This field cannot be configured when `kind` is set to `Storage` (V1).

* `change_feed_enabled` - (Optional) Is the blob service properties for change feed events enabled? Default to `false`.

-> **NOTE:** This field cannot be configured when `kind` is set to `Storage` (V1).

* `change_feed_retention_in_days` - (Optional) The duration of change feed events retention in days. The possible values are between 1 and 146000 days (400 years). Setting this to null (or omit this in the configuration file) indicates an infinite retention of the change feed.

-> **NOTE:** This field cannot be configured when `kind` is set to `Storage` (V1).

* `default_service_version` - (Optional) The API Version which should be used by default for requests to the Data Plane API if an incoming request doesn't specify an API Version.

* `last_access_time_enabled` - (Optional) Is the last access time based tracking enabled? Default to `false`.

-> **NOTE:** This field cannot be configured when `kind` is set to `Storage` (V1).

* `container_delete_retention_policy` - (Optional) A `container_delete_retention_policy` block as defined below.

---
Expand Down

0 comments on commit f50e3ca

Please sign in to comment.