Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New resource - azurerm_storage_account_blob_settings #3807

Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions azurerm/internal/services/storage/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ type Client struct {
AccountsClient *storage.AccountsClient
FileSystemsClient *filesystems.Client
ManagementPoliciesClient storage.ManagementPoliciesClient

environment az.Environment
BlobServicesClient storage.BlobServicesClient
environment az.Environment
}

func NewClient(options *common.ClientOptions) *Client {
Expand All @@ -37,12 +37,16 @@ func NewClient(options *common.ClientOptions) *Client {
managementPoliciesClient := storage.NewManagementPoliciesClientWithBaseURI(options.ResourceManagerEndpoint, options.SubscriptionId)
options.ConfigureClient(&managementPoliciesClient.Client, options.ResourceManagerAuthorizer)

blobServicesClient := storage.NewBlobServicesClientWithBaseURI(options.ResourceManagerEndpoint, options.SubscriptionId)
options.ConfigureClient(&blobServicesClient.Client, options.ResourceManagerAuthorizer)

// TODO: switch Storage Containers to using the storage.BlobContainersClient
// (which should fix #2977) when the storage clients have been moved in here
return &Client{
AccountsClient: &accountsClient,
FileSystemsClient: &fileSystemsClient,
ManagementPoliciesClient: managementPoliciesClient,
BlobServicesClient: blobServicesClient,
environment: options.Environment,
}
}
Expand Down
105 changes: 105 additions & 0 deletions azurerm/resource_arm_storage_account.go
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,32 @@ func resourceArmStorageAccount() *schema.Resource {
},
},

"blob_properties": {
Type: schema.TypeList,
Optional: true,
Computed: true,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"delete_retention_policy": {
Type: schema.TypeList,
Optional: true,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"days": {
Type: schema.TypeInt,
Optional: true,
Default: 7,
ValidateFunc: validation.IntBetween(1, 365),
},
},
},
},
},
},
},

"queue_properties": {
Type: schema.TypeList,
Optional: true,
Expand Down Expand Up @@ -754,6 +780,16 @@ func resourceArmStorageAccountCreate(d *schema.ResourceData, meta interface{}) e
}
}

if val, ok := d.GetOk("blob_properties"); ok {
blobClient := meta.(*ArmClient).Storage.BlobServicesClient

blobProperties := expandBlobProperties(val.([]interface{}))

if _, err = blobClient.SetServiceProperties(ctx, resourceGroupName, storageAccountName, blobProperties); err != nil {
return fmt.Errorf("Error updating Azure Storage Account `blob_properties` %q: %+v", storageAccountName, err)
}
}

if val, ok := d.GetOk("queue_properties"); ok {
storageClient := meta.(*ArmClient).Storage
account, err := storageClient.FindAccount(ctx, storageAccountName)
Expand Down Expand Up @@ -960,6 +996,17 @@ func resourceArmStorageAccountUpdate(d *schema.ResourceData, meta interface{}) e
d.SetPartial("enable_advanced_threat_protection")
}

if d.HasChange("blob_properties") {
blobClient := meta.(*ArmClient).Storage.BlobServicesClient
blobProperties := expandBlobProperties(d.Get("blob_properties").([]interface{}))

if _, err = blobClient.SetServiceProperties(ctx, resourceGroupName, storageAccountName, blobProperties); err != nil {
return fmt.Errorf("Error updating Azure Storage Account `blob_properties` %q: %+v", storageAccountName, err)
}

d.SetPartial("blob_properties")
}

if d.HasChange("queue_properties") {
storageClient := meta.(*ArmClient).Storage
account, err := storageClient.FindAccount(ctx, storageAccountName)
Expand Down Expand Up @@ -1162,6 +1209,19 @@ func resourceArmStorageAccountRead(d *schema.ResourceData, meta interface{}) err
return fmt.Errorf("Unable to locate Storage Account %q!", name)
}

blobClient := storageClient.BlobServicesClient

blobProps, err := blobClient.GetServiceProperties(ctx, resGroup, name)
if err != nil {
if blobProps.Response.Response != nil && !utils.ResponseWasNotFound(blobProps.Response) {
return fmt.Errorf("Error reading blob properties for AzureRM Storage Account %q: %+v", name, err)
}
}

if err := d.Set("blob_properties", flattenBlobProperties(blobProps)); err != nil {
return fmt.Errorf("Error setting `blob_properties `for AzureRM Storage Account %q: %+v", name, err)
}

queueClient, err := storageClient.QueuesClient(ctx, *account)
if err != nil {
return fmt.Errorf("Error building Queues Client: %s", err)
Expand Down Expand Up @@ -1341,6 +1401,30 @@ func expandStorageAccountBypass(networkRule map[string]interface{}) storage.Bypa
return storage.Bypass(strings.Join(bypassValues, ", "))
}

func expandBlobProperties(input []interface{}) storage.BlobServiceProperties {
properties := storage.BlobServiceProperties{
BlobServicePropertiesProperties: &storage.BlobServicePropertiesProperties{
DeleteRetentionPolicy: &storage.DeleteRetentionPolicy{
Enabled: utils.Bool(false),
},
},
}
if len(input) == 0 {
return properties
}

blobAttr := input[0].(map[string]interface{})
deletePolicy := blobAttr["delete_retention_policy"].([]interface{})
if len(deletePolicy) > 0 {
policy := deletePolicy[0].(map[string]interface{})
days := policy["days"].(int)
properties.BlobServicePropertiesProperties.DeleteRetentionPolicy.Enabled = utils.Bool(true)
properties.BlobServicePropertiesProperties.DeleteRetentionPolicy.Days = utils.Int32(int32(days))
}

return properties
}

func expandQueueProperties(input []interface{}) (queues.StorageServiceProperties, error) {
var err error
properties := queues.StorageServiceProperties{}
Expand Down Expand Up @@ -1484,6 +1568,27 @@ func flattenStorageAccountVirtualNetworks(input *[]storage.VirtualNetworkRule) [
return virtualNetworks
}

func flattenBlobProperties(input storage.BlobServiceProperties) []interface{} {
if input.BlobServicePropertiesProperties == nil {
return []interface{}{}
}

blobProperties := make(map[string]interface{})

if deletePolicy := input.BlobServicePropertiesProperties.DeleteRetentionPolicy; deletePolicy != nil {
if enabled := deletePolicy.Enabled; enabled != nil && *enabled {
deleteRetentionPolicy := make([]interface{}, 0)
attr := make(map[string]interface{})

attr["days"] = int(*deletePolicy.Days)

blobProperties["delete_retention_policy"] = append(deleteRetentionPolicy, attr)
}
}

return []interface{}{blobProperties}
}

func flattenQueueProperties(input queues.StorageServicePropertiesResponse) []interface{} {
if input.Response.Response == nil {
return []interface{}{}
Expand Down
88 changes: 88 additions & 0 deletions azurerm/resource_arm_storage_account_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -748,6 +748,47 @@ func TestAccAzureRMStorageAccount_enableAdvancedThreatProtection(t *testing.T) {
})
}

func TestAccAzureRMStorageAccount_blobProperties(t *testing.T) {
resourceName := "azurerm_storage_account.testsa"
ri := tf.AccRandTimeInt()
rs := acctest.RandString(4)
location := testLocation()
preConfig := testAccAzureRMStorageAccount_blobProperties(ri, rs, location)
postConfig := testAccAzureRMStorageAccount_blobPropertiesUpdated(ri, rs, location)

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testCheckAzureRMStorageAccountDestroy,
Steps: []resource.TestStep{
{
Config: preConfig,
Check: resource.ComposeTestCheckFunc(
testCheckAzureRMStorageAccountExists(resourceName),
resource.TestCheckResourceAttr("azurerm_storage_account.testsa", "blob_properties.0.delete_retention_policy.0.days", "300"),
),
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
},
{
Config: postConfig,
Check: resource.ComposeTestCheckFunc(
testCheckAzureRMStorageAccountExists(resourceName),
resource.TestCheckResourceAttr("azurerm_storage_account.testsa", "blob_properties.0.delete_retention_policy.0.days", "7"),
),
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
},
},
})
}

func TestAccAzureRMStorageAccount_queueProperties(t *testing.T) {
resourceName := "azurerm_storage_account.testsa"
ri := tf.AccRandTimeInt()
Expand Down Expand Up @@ -1509,6 +1550,53 @@ resource "azurerm_storage_account" "testsa" {
`, rInt, location, rString)
}

func testAccAzureRMStorageAccount_blobProperties(rInt int, rString string, location string) string {
return fmt.Sprintf(`
resource "azurerm_resource_group" "testrg" {
name = "acctestAzureRMSA-%d"
location = "%s"
}

resource "azurerm_storage_account" "testsa" {
name = "unlikely23exst2acct%s"
resource_group_name = "${azurerm_resource_group.testrg.name}"

location = "${azurerm_resource_group.testrg.location}"
account_tier = "Standard"
account_replication_type = "LRS"

blob_properties {
delete_retention_policy {
days = 300
}
}
}
`, rInt, location, rString)
}

func testAccAzureRMStorageAccount_blobPropertiesUpdated(rInt int, rString string, location string) string {
return fmt.Sprintf(`
resource "azurerm_resource_group" "testrg" {
name = "acctestAzureRMSA-%d"
location = "%s"
}

resource "azurerm_storage_account" "testsa" {
name = "unlikely23exst2acct%s"
resource_group_name = "${azurerm_resource_group.testrg.name}"

location = "${azurerm_resource_group.testrg.location}"
account_tier = "Standard"
account_replication_type = "LRS"

blob_properties {
delete_retention_policy {
}
}
}
`, rInt, location, rString)
}

func testAccAzureRMStorageAccount_queueProperties(rInt int, rString string, location string) string {
return fmt.Sprintf(`
resource "azurerm_resource_group" "testrg" {
Expand Down
14 changes: 14 additions & 0 deletions website/docs/r/storage_account.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,8 @@ The following arguments are supported:

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

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

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

~> **NOTE:** `queue_properties` cannot be set when the `access_tier` is set to `BlobStorage`
Expand All @@ -122,6 +124,12 @@ The following arguments are supported:

---

A `blob_properties` block supports the following:

* `delete_retention_policy` - (Optional) block as defined below.

---

A `cors_rule` block supports the following:

* `allowed_headers` - (Required) A list of headers that are allowed to be a part of the cross-origin request.
Expand All @@ -142,6 +150,12 @@ A `custom_domain` block supports the following:
* `name` - (Optional) The Custom Domain Name to use for the Storage Account, which will be validated by Azure.
* `use_subdomain` - (Optional) Should the Custom Domain Name be validated by using indirect CNAME validation?

---

A `delete_retention_policy` block supports the following:

* `days` - (Optional) Specifies the number of days that the blob should be retained. The minimum specified value can be 1 and the maximum value can be 365. Defaults to 7.

---

A `hour_metrics` block supports the following:
Expand Down