From e621a8cac6bf74bee97b90ee778aa0eade7530e2 Mon Sep 17 00:00:00 2001 From: Benjamin Weimer Date: Wed, 3 Jul 2019 11:00:56 +0200 Subject: [PATCH 1/9] new resource azurerm_storage_account_blob_settings --- azurerm/config.go | 9 +- azurerm/provider.go | 1 + ...ource_arm_storage_account_blob_settings.go | 177 ++++++++++++++++++ ..._arm_storage_account_blob_settings_test.go | 124 ++++++++++++ ...torage_account_blob_settings.html.markdown | 61 ++++++ 5 files changed, 370 insertions(+), 2 deletions(-) create mode 100644 azurerm/resource_arm_storage_account_blob_settings.go create mode 100644 azurerm/resource_arm_storage_account_blob_settings_test.go create mode 100644 website/docs/r/storage_account_blob_settings.html.markdown diff --git a/azurerm/config.go b/azurerm/config.go index 1a4f539fd14a..6c5f3c50b594 100644 --- a/azurerm/config.go +++ b/azurerm/config.go @@ -265,8 +265,9 @@ type ArmClient struct { subscriptionsClient subscriptions.Client // Storage - storageServiceClient storage.AccountsClient - storageUsageClient storage.UsagesClient + storageServiceClient storage.AccountsClient + storageUsageClient storage.UsagesClient + storageBlobServicesClient storage.BlobServicesClient // Stream Analytics streamAnalyticsFunctionsClient streamanalytics.FunctionsClient @@ -1092,6 +1093,10 @@ func (c *ArmClient) registerStorageClients(endpoint, subscriptionId string, auth usageClient := storage.NewUsagesClientWithBaseURI(endpoint, subscriptionId) c.configureClient(&usageClient.Client, auth) c.storageUsageClient = usageClient + + blobServicesClient := storage.NewBlobServicesClientWithBaseURI(endpoint, subscriptionId) + c.configureClient(&blobServicesClient.Client, auth) + c.storageBlobServicesClient = blobServicesClient } func (c *ArmClient) registerStreamAnalyticsClients(endpoint, subscriptionId string, auth autorest.Authorizer) { diff --git a/azurerm/provider.go b/azurerm/provider.go index f0cb2f83835d..857157f8f7dd 100644 --- a/azurerm/provider.go +++ b/azurerm/provider.go @@ -416,6 +416,7 @@ func Provider() terraform.ResourceProvider { "azurerm_sql_server": resourceArmSqlServer(), "azurerm_sql_virtual_network_rule": resourceArmSqlVirtualNetworkRule(), "azurerm_storage_account": resourceArmStorageAccount(), + "azurerm_storage_account_blob_settings": resourceArmStorageAccountBlobSettings(), "azurerm_storage_blob": resourceArmStorageBlob(), "azurerm_storage_container": resourceArmStorageContainer(), "azurerm_storage_queue": resourceArmStorageQueue(), diff --git a/azurerm/resource_arm_storage_account_blob_settings.go b/azurerm/resource_arm_storage_account_blob_settings.go new file mode 100644 index 000000000000..339dd03ffcbe --- /dev/null +++ b/azurerm/resource_arm_storage_account_blob_settings.go @@ -0,0 +1,177 @@ +package azurerm + +import ( + "fmt" + "github.com/Azure/azure-sdk-for-go/services/storage/mgmt/2019-04-01/storage" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/tf" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" + "log" + + "github.com/hashicorp/terraform/helper/schema" + "github.com/hashicorp/terraform/helper/validation" +) + +var storageAccountBlobSettingsResourceName = "azurerm_storage_account_blob_settings" + +func resourceArmStorageAccountBlobSettings() *schema.Resource { + return &schema.Resource{ + Create: resourceArmStorageAccountBlobSettingsCreateUpdate, + Read: resourceArmStorageAccountBlobSettingsRead, + Update: resourceArmStorageAccountBlobSettingsCreateUpdate, + Delete: resourceArmStorageAccountBlobSettingsDelete, + Importer: &schema.ResourceImporter{ + State: schema.ImportStatePassthrough, + }, + + Schema: map[string]*schema.Schema{ + "resource_group_name": azure.SchemaResourceGroupName(), + + "storage_account_name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + + "enable_soft_delete": { + Type: schema.TypeBool, + Optional: true, + Default: false, + }, + + "soft_delete_retention_days": { + Type: schema.TypeInt, + Optional: true, + Default: 7, + ValidateFunc: validation.IntBetween(1, 365), + }, + }, + } +} + +func resourceArmStorageAccountBlobSettingsCreateUpdate(d *schema.ResourceData, meta interface{}) error { + client := meta.(*ArmClient).storageBlobServicesClient + ctx := meta.(*ArmClient).StopContext + + log.Printf("[INFO] preparing arguments for Azure ARM Storage Account Blob Settings creation.") + + resourceGroupName := d.Get("resource_group_name").(string) + storageAccountName := d.Get("storage_account_name").(string) + enableSoftDelete := d.Get("enable_soft_delete").(bool) + softDeleteRetentionDays := int32(d.Get("soft_delete_retention_days").(int)) + + if requireResourcesToBeImported && d.IsNewResource() { + existing, err := client.GetServiceProperties(ctx, resourceGroupName, storageAccountName) + if err != nil { + if !utils.ResponseWasNotFound(existing.Response) { + return fmt.Errorf("error checking for presence of existing Storage Account Blob Settings (Storage Account %q / Resource Group %q): %s", + storageAccountName, resourceGroupName, err) + } + } + + if existing.ID != nil && *existing.ID != "" { + return tf.ImportAsExistsError(storageAccountBlobSettingsResourceName, *existing.ID) + } + } + + properties := storage.BlobServicePropertiesProperties{ + DeleteRetentionPolicy: &storage.DeleteRetentionPolicy{ + Enabled: &enableSoftDelete, + Days: &softDeleteRetentionDays, + }, + } + + propertiesWrapper := storage.BlobServiceProperties{ + BlobServicePropertiesProperties: &properties, + } + + _, err := client.SetServiceProperties(ctx, resourceGroupName, storageAccountName, propertiesWrapper) + + if err != nil { + return fmt.Errorf("error while updataing Storage Account Blob Settings (Storage Account %q / Resource Group %q): %s", + storageAccountName, resourceGroupName, err) + } + + read, err := client.GetServiceProperties(ctx, resourceGroupName, storageAccountName) + + if err != nil || read.ID == nil { + return fmt.Errorf("can't read ID of Storage Account Blob Settings (Storage Account %q / Resource Group %q): %s", + storageAccountName, resourceGroupName, err) + } + + d.SetId(*read.ID) + + return resourceArmStorageAccountBlobSettingsRead(d, meta) +} + +func resourceArmStorageAccountBlobSettingsRead(d *schema.ResourceData, meta interface{}) error { + client := meta.(*ArmClient).storageBlobServicesClient + ctx := meta.(*ArmClient).StopContext + + log.Printf("[INFO] Reading Azure ARM Storage Account Blob Settings.") + + id, err := parseAzureResourceID(d.Id()) + + if err != nil { + return err + } + + resourceGroupName := id.ResourceGroup + storageAccountName := id.Path["storageAccounts"] + + resp, err := client.GetServiceProperties(ctx, resourceGroupName, storageAccountName) + + if err != nil { + if utils.ResponseWasNotFound(resp.Response) { + d.SetId("") + return nil + } + return fmt.Errorf("error making Read request on Azure Storage Account %q: %+v", storageAccountName, err) + } + + d.Set("resource_group_name", resourceGroupName) + d.Set("storage_account_name", storageAccountName) + + if props := resp.BlobServicePropertiesProperties; props != nil { + if policy := props.DeleteRetentionPolicy; policy != nil { + if policy.Enabled != nil { + d.Set("enable_soft_delete", policy.Enabled) + } + if policy.Days != nil { + d.Set("soft_delete_retention_days", policy.Days) + } + } + } + + return nil +} + +func resourceArmStorageAccountBlobSettingsDelete(d *schema.ResourceData, meta interface{}) error { + client := meta.(*ArmClient).storageBlobServicesClient + ctx := meta.(*ArmClient).StopContext + + id, err := parseAzureResourceID(d.Id()) + if err != nil { + return err + } + + resourceGroupName := id.ResourceGroup + storageAccountName := id.Path["storageAccounts"] + enableSoftDelete := false + propertiesWrapper := storage.BlobServiceProperties{ + BlobServicePropertiesProperties: &storage.BlobServicePropertiesProperties{ + DeleteRetentionPolicy: &storage.DeleteRetentionPolicy{ + Enabled: &enableSoftDelete, + }, + }, + } + + _, err = client.SetServiceProperties(ctx, resourceGroupName, storageAccountName, propertiesWrapper) + + if err != nil { + return fmt.Errorf("error deleting Storage Account Blob Settings (Storage Account %q / Resource Group %q): %s", + storageAccountName, resourceGroupName, err) + } + + return nil +} diff --git a/azurerm/resource_arm_storage_account_blob_settings_test.go b/azurerm/resource_arm_storage_account_blob_settings_test.go new file mode 100644 index 000000000000..d8f464782c38 --- /dev/null +++ b/azurerm/resource_arm_storage_account_blob_settings_test.go @@ -0,0 +1,124 @@ +package azurerm + +import ( + "fmt" + "github.com/hashicorp/terraform/helper/acctest" + "github.com/hashicorp/terraform/helper/resource" + "github.com/hashicorp/terraform/terraform" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/tf" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" + "testing" +) + +func TestAccAzureRMStorageAccountBlobSettings_basic(t *testing.T) { + resourceName := "azurerm_storage_account_blob_settings.testsabs" + storageAccountResourceName := "azurerm_storage_account.testsa" + ri := tf.AccRandTimeInt() + rs := acctest.RandString(4) + location := testLocation() + createConfig := testAccAzureRMStorageAccountBlobSettings_basic(ri, rs, location) + updateConfig := testAccAzureRMStorageAccountBlobSettings_update(ri, rs, location) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMStorageAccountBlobSettingsDestroy, + Steps: []resource.TestStep{ + { + Config: createConfig, + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMStorageAccountExists(storageAccountResourceName), + resource.TestCheckResourceAttr(resourceName, "enable_soft_delete", "true"), + resource.TestCheckResourceAttr(resourceName, "soft_delete_retention_days", "123"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + { + Config: updateConfig, + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMStorageAccountExists(storageAccountResourceName), + resource.TestCheckResourceAttr(resourceName, "enable_soft_delete", "true"), + resource.TestCheckResourceAttr(resourceName, "soft_delete_retention_days", "99"), + ), + }, + }, + }) +} + +func testAccAzureRMStorageAccountBlobSettings_basic(rInt int, rString string, location string) string { + return fmt.Sprintf(` +resource "azurerm_resource_group" "testrg" { + name = "acctestAzureRMSABS-%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" +} + +resource "azurerm_storage_account_blob_settings" "testsabs" { + resource_group_name = "${azurerm_resource_group.testrg.name}" + storage_account_name = "${azurerm_storage_account.testsa.name}" + enable_soft_delete = true + soft_delete_retention_days = 123 +} +`, rInt, location, rString) +} + +func testAccAzureRMStorageAccountBlobSettings_update(rInt int, rString string, location string) string { + return fmt.Sprintf(` +resource "azurerm_resource_group" "testrg" { + name = "acctestAzureRMSABS-%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" +} + +resource "azurerm_storage_account_blob_settings" "testsabs" { + resource_group_name = "${azurerm_resource_group.testrg.name}" + storage_account_name = "${azurerm_storage_account.testsa.name}" + enable_soft_delete = true + soft_delete_retention_days = 99 +} +`, rInt, location, rString) +} + +func testCheckAzureRMStorageAccountBlobSettingsDestroy(s *terraform.State) error { + client := testAccProvider.Meta().(*ArmClient).storageBlobServicesClient + ctx := testAccProvider.Meta().(*ArmClient).StopContext + + for _, rs := range s.RootModule().Resources { + if rs.Type != "azurerm_storage_account_blob_settings" { + continue + } + + storageAccountName := rs.Primary.Attributes["storage_account_name"] + resourceGroupName := rs.Primary.Attributes["resource_group_name"] + + resp, err := client.GetServiceProperties(ctx, resourceGroupName, storageAccountName) + if err != nil { + if !utils.ResponseWasNotFound(resp.Response) { + return fmt.Errorf("Storage Account Blob Settings still exist:\n%#v", resp.BlobServicePropertiesProperties) + } + return nil + } + } + + return nil +} diff --git a/website/docs/r/storage_account_blob_settings.html.markdown b/website/docs/r/storage_account_blob_settings.html.markdown new file mode 100644 index 000000000000..f7e304cd5dd9 --- /dev/null +++ b/website/docs/r/storage_account_blob_settings.html.markdown @@ -0,0 +1,61 @@ +--- +layout: "azurerm" +page_title: "Azure Resource Manager: azurerm_storage_account_blob_settings" +sidebar_current: "docs-azurerm-resource-azurerm-storage-account-blob-settings" +description: |- + Manages Azure Storage Account Blob Properties. +--- + +# azurerm_storage_account_blob_settings + +Manages Azure Storage Account Blob Properties. + +## Example Usage + +```hcl +resource "azurerm_resource_group" "testrg" { + name = "resourceGroupName" + location = "westus" +} + +resource "azurerm_storage_account" "testsa" { + name = "storageaccountname" + resource_group_name = "${azurerm_resource_group.testrg.name}" + location = "westus" + account_tier = "Standard" + account_replication_type = "LRS" +} + +resource "azurerm_storage_account_blob_settings" "testsabs" { + resource_group_name = "${azurerm_resource_group.testrg.name}" + storage_account_name = "${azurerm_storage_account.testsa.name}" + enable_soft_delete = true + soft_delete_retention_days = 123 +} +``` + +## Argument Reference + +The following arguments are supported: + +* `resource_group_name` - (Required) The name of the resource group in which to create the storage account. Changing this forces a new resource to be created. + +* `storage_account_name` - (Required) Specifies the name of the storage account the blob settings are applied to. + +* `enable_soft_delete` - (Optional) Boolean flag which controls whether soft delete is enabled or not. Defaults to `false`. + +* `soft_delete_retention_days` - (Optional) Specifies the number of days that the blob should be retained. The minimum specified value can be 1 an the maximum value can be 365. Defaults to `7`. + +## Attributes Reference + +The following attributes are exported in addition to the arguments listed above: + +* `id` - The ID of the Storage Account Blob Settings. + +## Import + +Storage Accounts can be imported using the `resource id`, e.g. + +```shell +terraform import azurerm_storage_account_blob_settings.storageAccBlobSettings /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/myresourcegroup/providers/Microsoft.Storage/storageAccounts/myaccount/blobServices/default +``` From 7238ae05ed0118961fa0f33b90d1f6c130b5fa45 Mon Sep 17 00:00:00 2001 From: Benjamin Weimer Date: Mon, 8 Jul 2019 15:37:32 +0200 Subject: [PATCH 2/9] fix import order --- azurerm/resource_arm_storage_account_blob_settings.go | 8 ++++---- .../resource_arm_storage_account_blob_settings_test.go | 3 ++- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/azurerm/resource_arm_storage_account_blob_settings.go b/azurerm/resource_arm_storage_account_blob_settings.go index 339dd03ffcbe..e17482ba51e3 100644 --- a/azurerm/resource_arm_storage_account_blob_settings.go +++ b/azurerm/resource_arm_storage_account_blob_settings.go @@ -2,14 +2,14 @@ package azurerm import ( "fmt" - "github.com/Azure/azure-sdk-for-go/services/storage/mgmt/2019-04-01/storage" - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure" - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/tf" - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" "log" + "github.com/Azure/azure-sdk-for-go/services/storage/mgmt/2019-04-01/storage" "github.com/hashicorp/terraform/helper/schema" "github.com/hashicorp/terraform/helper/validation" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/tf" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" ) var storageAccountBlobSettingsResourceName = "azurerm_storage_account_blob_settings" diff --git a/azurerm/resource_arm_storage_account_blob_settings_test.go b/azurerm/resource_arm_storage_account_blob_settings_test.go index d8f464782c38..a2d69df4953c 100644 --- a/azurerm/resource_arm_storage_account_blob_settings_test.go +++ b/azurerm/resource_arm_storage_account_blob_settings_test.go @@ -2,12 +2,13 @@ package azurerm import ( "fmt" + "testing" + "github.com/hashicorp/terraform/helper/acctest" "github.com/hashicorp/terraform/helper/resource" "github.com/hashicorp/terraform/terraform" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/tf" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" - "testing" ) func TestAccAzureRMStorageAccountBlobSettings_basic(t *testing.T) { From f73397cd7e81fedf8ae5d960e36eb6ad755de360 Mon Sep 17 00:00:00 2001 From: Benjamin Weimer <50862958+benjamin37@users.noreply.github.com> Date: Tue, 9 Jul 2019 16:16:12 +0200 Subject: [PATCH 3/9] resolve conflicts with master --- azurerm/config.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/azurerm/config.go b/azurerm/config.go index 5b12e51a7ce6..e18c918a3733 100644 --- a/azurerm/config.go +++ b/azurerm/config.go @@ -1104,7 +1104,7 @@ func (c *ArmClient) registerStorageClients(endpoint, subscriptionId string, auth c.configureClient(&blobServicesClient.Client, auth) c.storageBlobServicesClient = blobServicesClient - c.storage = intStor.BuildClient(accountsClient) + c.storage = intStor.BuildClient(accountsClient) } func (c *ArmClient) registerStreamAnalyticsClients(endpoint, subscriptionId string, auth autorest.Authorizer) { From ffedffdf3ae727113a2882e4c01c5cae16948dc9 Mon Sep 17 00:00:00 2001 From: Benjamin Weimer Date: Tue, 9 Jul 2019 16:47:25 +0200 Subject: [PATCH 4/9] remove whitespaces --- azurerm/config.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/azurerm/config.go b/azurerm/config.go index e18c918a3733..9f20875bc9cd 100644 --- a/azurerm/config.go +++ b/azurerm/config.go @@ -1103,7 +1103,7 @@ func (c *ArmClient) registerStorageClients(endpoint, subscriptionId string, auth blobServicesClient := storage.NewBlobServicesClientWithBaseURI(endpoint, subscriptionId) c.configureClient(&blobServicesClient.Client, auth) c.storageBlobServicesClient = blobServicesClient - + c.storage = intStor.BuildClient(accountsClient) } From 975a665a7a282c044d07886c77a43b6b7d654535 Mon Sep 17 00:00:00 2001 From: Benjamin Weimer Date: Thu, 7 Nov 2019 14:28:54 +0100 Subject: [PATCH 5/9] remove unnecessary nil check --- azurerm/resource_arm_storage_account_blob_settings.go | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/azurerm/resource_arm_storage_account_blob_settings.go b/azurerm/resource_arm_storage_account_blob_settings.go index 0e327d78ca84..f883deb6cd84 100644 --- a/azurerm/resource_arm_storage_account_blob_settings.go +++ b/azurerm/resource_arm_storage_account_blob_settings.go @@ -134,12 +134,8 @@ func resourceArmStorageAccountBlobSettingsRead(d *schema.ResourceData, meta inte if props := resp.BlobServicePropertiesProperties; props != nil { if policy := props.DeleteRetentionPolicy; policy != nil { - if policy.Enabled != nil { - d.Set("enable_soft_delete", policy.Enabled) - } - if policy.Days != nil { - d.Set("soft_delete_retention_days", policy.Days) - } + d.Set("enable_soft_delete", policy.Enabled) + d.Set("soft_delete_retention_days", policy.Days) } } From 072308080e19072cfe2e6d94242178b2c9020087 Mon Sep 17 00:00:00 2001 From: Benjamin Weimer Date: Fri, 8 Nov 2019 12:23:12 +0100 Subject: [PATCH 6/9] move blob_properties in storage account --- azurerm/provider.go | 1 - azurerm/resource_arm_storage_account.go | 107 ++++++++++- ...ource_arm_storage_account_blob_settings.go | 173 ------------------ ..._arm_storage_account_blob_settings_test.go | 125 ------------- azurerm/resource_arm_storage_account_test.go | 88 +++++++++ website/docs/r/storage_account.html.markdown | 14 ++ ...torage_account_blob_settings.html.markdown | 61 ------ 7 files changed, 208 insertions(+), 361 deletions(-) delete mode 100644 azurerm/resource_arm_storage_account_blob_settings.go delete mode 100644 azurerm/resource_arm_storage_account_blob_settings_test.go delete mode 100644 website/docs/r/storage_account_blob_settings.html.markdown diff --git a/azurerm/provider.go b/azurerm/provider.go index 29a83bb2567d..43c9ffb6e118 100644 --- a/azurerm/provider.go +++ b/azurerm/provider.go @@ -429,7 +429,6 @@ func Provider() terraform.ResourceProvider { "azurerm_sql_server": resourceArmSqlServer(), "azurerm_sql_virtual_network_rule": resourceArmSqlVirtualNetworkRule(), "azurerm_storage_account": resourceArmStorageAccount(), - "azurerm_storage_account_blob_settings": resourceArmStorageAccountBlobSettings(), "azurerm_storage_blob": resourceArmStorageBlob(), "azurerm_storage_container": resourceArmStorageContainer(), "azurerm_storage_data_lake_gen2_filesystem": resourceArmStorageDataLakeGen2FileSystem(), diff --git a/azurerm/resource_arm_storage_account.go b/azurerm/resource_arm_storage_account.go index b06ca8d356cf..f51b6e3c94f1 100644 --- a/azurerm/resource_arm_storage_account.go +++ b/azurerm/resource_arm_storage_account.go @@ -11,11 +11,11 @@ import ( "github.com/Azure/azure-sdk-for-go/services/preview/security/mgmt/v1.0/security" "github.com/Azure/azure-sdk-for-go/services/storage/mgmt/2019-04-01/storage" azautorest "github.com/Azure/go-autorest/autorest" + "github.com/hashicorp/go-azure-helpers/response" "github.com/hashicorp/go-getter/helper/url" "github.com/hashicorp/terraform-plugin-sdk/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/helper/validation" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure" - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/response" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/suppress" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/tf" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/validate" @@ -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, @@ -751,6 +777,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) @@ -954,6 +990,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) @@ -1156,6 +1203,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) @@ -1327,6 +1387,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{} @@ -1470,6 +1554,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{}{} diff --git a/azurerm/resource_arm_storage_account_blob_settings.go b/azurerm/resource_arm_storage_account_blob_settings.go deleted file mode 100644 index f883deb6cd84..000000000000 --- a/azurerm/resource_arm_storage_account_blob_settings.go +++ /dev/null @@ -1,173 +0,0 @@ -package azurerm - -import ( - "fmt" - "log" - - "github.com/Azure/azure-sdk-for-go/services/storage/mgmt/2019-04-01/storage" - "github.com/hashicorp/terraform-plugin-sdk/helper/schema" - "github.com/hashicorp/terraform-plugin-sdk/helper/validation" - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure" - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/tf" - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" -) - -var storageAccountBlobSettingsResourceName = "azurerm_storage_account_blob_settings" - -func resourceArmStorageAccountBlobSettings() *schema.Resource { - return &schema.Resource{ - Create: resourceArmStorageAccountBlobSettingsCreateUpdate, - Read: resourceArmStorageAccountBlobSettingsRead, - Update: resourceArmStorageAccountBlobSettingsCreateUpdate, - Delete: resourceArmStorageAccountBlobSettingsDelete, - Importer: &schema.ResourceImporter{ - State: schema.ImportStatePassthrough, - }, - - Schema: map[string]*schema.Schema{ - "resource_group_name": azure.SchemaResourceGroupName(), - - "storage_account_name": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - }, - - "enable_soft_delete": { - Type: schema.TypeBool, - Optional: true, - Default: false, - }, - - "soft_delete_retention_days": { - Type: schema.TypeInt, - Optional: true, - Default: 7, - ValidateFunc: validation.IntBetween(1, 365), - }, - }, - } -} - -func resourceArmStorageAccountBlobSettingsCreateUpdate(d *schema.ResourceData, meta interface{}) error { - client := meta.(*ArmClient).Storage.BlobServicesClient - ctx := meta.(*ArmClient).StopContext - - log.Printf("[INFO] preparing arguments for Azure ARM Storage Account Blob Settings creation.") - - resourceGroupName := d.Get("resource_group_name").(string) - storageAccountName := d.Get("storage_account_name").(string) - enableSoftDelete := d.Get("enable_soft_delete").(bool) - softDeleteRetentionDays := int32(d.Get("soft_delete_retention_days").(int)) - - if requireResourcesToBeImported && d.IsNewResource() { - existing, err := client.GetServiceProperties(ctx, resourceGroupName, storageAccountName) - if err != nil { - if !utils.ResponseWasNotFound(existing.Response) { - return fmt.Errorf("error checking for presence of existing Storage Account Blob Settings (Storage Account %q / Resource Group %q): %s", - storageAccountName, resourceGroupName, err) - } - } - - if existing.ID != nil && *existing.ID != "" { - return tf.ImportAsExistsError(storageAccountBlobSettingsResourceName, *existing.ID) - } - } - - properties := storage.BlobServicePropertiesProperties{ - DeleteRetentionPolicy: &storage.DeleteRetentionPolicy{ - Enabled: &enableSoftDelete, - Days: &softDeleteRetentionDays, - }, - } - - propertiesWrapper := storage.BlobServiceProperties{ - BlobServicePropertiesProperties: &properties, - } - - _, err := client.SetServiceProperties(ctx, resourceGroupName, storageAccountName, propertiesWrapper) - - if err != nil { - return fmt.Errorf("error while updataing Storage Account Blob Settings (Storage Account %q / Resource Group %q): %s", - storageAccountName, resourceGroupName, err) - } - - read, err := client.GetServiceProperties(ctx, resourceGroupName, storageAccountName) - - if err != nil || read.ID == nil { - return fmt.Errorf("can't read ID of Storage Account Blob Settings (Storage Account %q / Resource Group %q): %s", - storageAccountName, resourceGroupName, err) - } - - d.SetId(*read.ID) - - return resourceArmStorageAccountBlobSettingsRead(d, meta) -} - -func resourceArmStorageAccountBlobSettingsRead(d *schema.ResourceData, meta interface{}) error { - client := meta.(*ArmClient).Storage.BlobServicesClient - ctx := meta.(*ArmClient).StopContext - - log.Printf("[INFO] Reading Azure ARM Storage Account Blob Settings.") - - id, err := parseAzureResourceID(d.Id()) - - if err != nil { - return err - } - - resourceGroupName := id.ResourceGroup - storageAccountName := id.Path["storageAccounts"] - - resp, err := client.GetServiceProperties(ctx, resourceGroupName, storageAccountName) - - if err != nil { - if utils.ResponseWasNotFound(resp.Response) { - d.SetId("") - return nil - } - return fmt.Errorf("error making Read request on Azure Storage Account %q: %+v", storageAccountName, err) - } - - d.Set("resource_group_name", resourceGroupName) - d.Set("storage_account_name", storageAccountName) - - if props := resp.BlobServicePropertiesProperties; props != nil { - if policy := props.DeleteRetentionPolicy; policy != nil { - d.Set("enable_soft_delete", policy.Enabled) - d.Set("soft_delete_retention_days", policy.Days) - } - } - - return nil -} - -func resourceArmStorageAccountBlobSettingsDelete(d *schema.ResourceData, meta interface{}) error { - client := meta.(*ArmClient).Storage.BlobServicesClient - ctx := meta.(*ArmClient).StopContext - - id, err := parseAzureResourceID(d.Id()) - if err != nil { - return err - } - - resourceGroupName := id.ResourceGroup - storageAccountName := id.Path["storageAccounts"] - enableSoftDelete := false - propertiesWrapper := storage.BlobServiceProperties{ - BlobServicePropertiesProperties: &storage.BlobServicePropertiesProperties{ - DeleteRetentionPolicy: &storage.DeleteRetentionPolicy{ - Enabled: &enableSoftDelete, - }, - }, - } - - _, err = client.SetServiceProperties(ctx, resourceGroupName, storageAccountName, propertiesWrapper) - - if err != nil { - return fmt.Errorf("error deleting Storage Account Blob Settings (Storage Account %q / Resource Group %q): %s", - storageAccountName, resourceGroupName, err) - } - - return nil -} diff --git a/azurerm/resource_arm_storage_account_blob_settings_test.go b/azurerm/resource_arm_storage_account_blob_settings_test.go deleted file mode 100644 index e21eb5aac0a2..000000000000 --- a/azurerm/resource_arm_storage_account_blob_settings_test.go +++ /dev/null @@ -1,125 +0,0 @@ -package azurerm - -import ( - "fmt" - "testing" - - "github.com/hashicorp/terraform-plugin-sdk/helper/resource" - "github.com/hashicorp/terraform-plugin-sdk/terraform" - "github.com/hashicorp/terraform/helper/acctest" - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/tf" - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" -) - -func TestAccAzureRMStorageAccountBlobSettings_basic(t *testing.T) { - resourceName := "azurerm_storage_account_blob_settings.testsabs" - storageAccountResourceName := "azurerm_storage_account.testsa" - ri := tf.AccRandTimeInt() - rs := acctest.RandString(4) - location := testLocation() - createConfig := testAccAzureRMStorageAccountBlobSettings_basic(ri, rs, location) - updateConfig := testAccAzureRMStorageAccountBlobSettings_update(ri, rs, location) - - resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, - CheckDestroy: testCheckAzureRMStorageAccountBlobSettingsDestroy, - Steps: []resource.TestStep{ - { - Config: createConfig, - Check: resource.ComposeTestCheckFunc( - testCheckAzureRMStorageAccountExists(storageAccountResourceName), - resource.TestCheckResourceAttr(resourceName, "enable_soft_delete", "true"), - resource.TestCheckResourceAttr(resourceName, "soft_delete_retention_days", "123"), - ), - }, - { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, - }, - { - Config: updateConfig, - Check: resource.ComposeTestCheckFunc( - testCheckAzureRMStorageAccountExists(storageAccountResourceName), - resource.TestCheckResourceAttr(resourceName, "enable_soft_delete", "true"), - resource.TestCheckResourceAttr(resourceName, "soft_delete_retention_days", "99"), - ), - }, - }, - }) -} - -func testAccAzureRMStorageAccountBlobSettings_basic(rInt int, rString string, location string) string { - return fmt.Sprintf(` -resource "azurerm_resource_group" "testrg" { - name = "acctestAzureRMSABS-%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" -} - -resource "azurerm_storage_account_blob_settings" "testsabs" { - resource_group_name = "${azurerm_resource_group.testrg.name}" - storage_account_name = "${azurerm_storage_account.testsa.name}" - enable_soft_delete = true - soft_delete_retention_days = 123 -} -`, rInt, location, rString) -} - -func testAccAzureRMStorageAccountBlobSettings_update(rInt int, rString string, location string) string { - return fmt.Sprintf(` -resource "azurerm_resource_group" "testrg" { - name = "acctestAzureRMSABS-%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" -} - -resource "azurerm_storage_account_blob_settings" "testsabs" { - resource_group_name = "${azurerm_resource_group.testrg.name}" - storage_account_name = "${azurerm_storage_account.testsa.name}" - enable_soft_delete = true - soft_delete_retention_days = 99 -} -`, rInt, location, rString) -} - -func testCheckAzureRMStorageAccountBlobSettingsDestroy(s *terraform.State) error { - client := testAccProvider.Meta().(*ArmClient).Storage.BlobServicesClient - ctx := testAccProvider.Meta().(*ArmClient).StopContext - - for _, rs := range s.RootModule().Resources { - if rs.Type != "azurerm_storage_account_blob_settings" { - continue - } - - storageAccountName := rs.Primary.Attributes["storage_account_name"] - resourceGroupName := rs.Primary.Attributes["resource_group_name"] - - resp, err := client.GetServiceProperties(ctx, resourceGroupName, storageAccountName) - if err != nil { - if !utils.ResponseWasNotFound(resp.Response) { - return fmt.Errorf("Storage Account Blob Settings still exist:\n%#v", resp.BlobServicePropertiesProperties) - } - return nil - } - } - - return nil -} diff --git a/azurerm/resource_arm_storage_account_test.go b/azurerm/resource_arm_storage_account_test.go index b8ff10bca0a2..fa0eed8ff4e7 100644 --- a/azurerm/resource_arm_storage_account_test.go +++ b/azurerm/resource_arm_storage_account_test.go @@ -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() @@ -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" { diff --git a/website/docs/r/storage_account.html.markdown b/website/docs/r/storage_account.html.markdown index 0b9847bf38da..150deb4d403e 100644 --- a/website/docs/r/storage_account.html.markdown +++ b/website/docs/r/storage_account.html.markdown @@ -111,6 +111,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` @@ -121,6 +123,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. @@ -141,6 +149,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: diff --git a/website/docs/r/storage_account_blob_settings.html.markdown b/website/docs/r/storage_account_blob_settings.html.markdown deleted file mode 100644 index f7e304cd5dd9..000000000000 --- a/website/docs/r/storage_account_blob_settings.html.markdown +++ /dev/null @@ -1,61 +0,0 @@ ---- -layout: "azurerm" -page_title: "Azure Resource Manager: azurerm_storage_account_blob_settings" -sidebar_current: "docs-azurerm-resource-azurerm-storage-account-blob-settings" -description: |- - Manages Azure Storage Account Blob Properties. ---- - -# azurerm_storage_account_blob_settings - -Manages Azure Storage Account Blob Properties. - -## Example Usage - -```hcl -resource "azurerm_resource_group" "testrg" { - name = "resourceGroupName" - location = "westus" -} - -resource "azurerm_storage_account" "testsa" { - name = "storageaccountname" - resource_group_name = "${azurerm_resource_group.testrg.name}" - location = "westus" - account_tier = "Standard" - account_replication_type = "LRS" -} - -resource "azurerm_storage_account_blob_settings" "testsabs" { - resource_group_name = "${azurerm_resource_group.testrg.name}" - storage_account_name = "${azurerm_storage_account.testsa.name}" - enable_soft_delete = true - soft_delete_retention_days = 123 -} -``` - -## Argument Reference - -The following arguments are supported: - -* `resource_group_name` - (Required) The name of the resource group in which to create the storage account. Changing this forces a new resource to be created. - -* `storage_account_name` - (Required) Specifies the name of the storage account the blob settings are applied to. - -* `enable_soft_delete` - (Optional) Boolean flag which controls whether soft delete is enabled or not. Defaults to `false`. - -* `soft_delete_retention_days` - (Optional) Specifies the number of days that the blob should be retained. The minimum specified value can be 1 an the maximum value can be 365. Defaults to `7`. - -## Attributes Reference - -The following attributes are exported in addition to the arguments listed above: - -* `id` - The ID of the Storage Account Blob Settings. - -## Import - -Storage Accounts can be imported using the `resource id`, e.g. - -```shell -terraform import azurerm_storage_account_blob_settings.storageAccBlobSettings /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/myresourcegroup/providers/Microsoft.Storage/storageAccounts/myaccount/blobServices/default -``` From 795e6157692781550dc81f0e92f91c8c4545d88b Mon Sep 17 00:00:00 2001 From: Benjamin Weimer Date: Mon, 16 Dec 2019 09:12:16 +0100 Subject: [PATCH 7/9] review comments, always set a delete_retention_policy, documentation changes --- azurerm/resource_arm_storage_account.go | 22 +++++++++++++------- website/docs/r/storage_account.html.markdown | 4 ++-- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/azurerm/resource_arm_storage_account.go b/azurerm/resource_arm_storage_account.go index 83556f9e3efd..a0abecb74e5f 100644 --- a/azurerm/resource_arm_storage_account.go +++ b/azurerm/resource_arm_storage_account.go @@ -1213,7 +1213,7 @@ func resourceArmStorageAccountRead(d *schema.ResourceData, meta interface{}) err blobProps, err := blobClient.GetServiceProperties(ctx, resGroup, name) if err != nil { - if blobProps.Response.Response != nil && !utils.ResponseWasNotFound(blobProps.Response) { + if !utils.ResponseWasNotFound(blobProps.Response) { return fmt.Errorf("Error reading blob properties for AzureRM Storage Account %q: %+v", name, err) } } @@ -1573,20 +1573,26 @@ func flattenBlobProperties(input storage.BlobServiceProperties) []interface{} { return []interface{}{} } - blobProperties := make(map[string]interface{}) + deleteRetentionPolicies := make([]interface{}, 0) 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) + days := 0 + if deletePolicy.Days != nil { + days = int(*deletePolicy.Days) + } - blobProperties["delete_retention_policy"] = append(deleteRetentionPolicy, attr) + deleteRetentionPolicies = append(deleteRetentionPolicies, map[string]interface{}{ + "days": days, + }) } } - return []interface{}{blobProperties} + return []interface{}{ + map[string]interface{}{ + "delete_retention_policy": deleteRetentionPolicies, + }, + } } func flattenQueueProperties(input queues.StorageServicePropertiesResponse) []interface{} { diff --git a/website/docs/r/storage_account.html.markdown b/website/docs/r/storage_account.html.markdown index 676ea5accea8..46b1ce73d31a 100644 --- a/website/docs/r/storage_account.html.markdown +++ b/website/docs/r/storage_account.html.markdown @@ -126,7 +126,7 @@ The following arguments are supported: A `blob_properties` block supports the following: -* `delete_retention_policy` - (Optional) block as defined below. +* `delete_retention_policy` - (Optional) A `delete_retention_policy` block as defined below. --- @@ -154,7 +154,7 @@ A `custom_domain` block supports the following: 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. +* `days` - (Optional) Specifies the number of days that the blob should be retained, between `1` and `365` days. Defaults to `7`. --- From 3533e12ffd96be0862c22e20a87d2bb1eb291b4e Mon Sep 17 00:00:00 2001 From: Benjamin Weimer Date: Mon, 16 Dec 2019 10:41:40 +0100 Subject: [PATCH 8/9] can set empty blob_properties --- azurerm/resource_arm_storage_account.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/azurerm/resource_arm_storage_account.go b/azurerm/resource_arm_storage_account.go index a0abecb74e5f..a6de74c73631 100644 --- a/azurerm/resource_arm_storage_account.go +++ b/azurerm/resource_arm_storage_account.go @@ -1409,7 +1409,7 @@ func expandBlobProperties(input []interface{}) storage.BlobServiceProperties { }, }, } - if len(input) == 0 { + if len(input) == 0 || input[0] == nil { return properties } From 13e7c43054bb09c759ab4db20b950fb927da208d Mon Sep 17 00:00:00 2001 From: Benjamin Weimer Date: Mon, 16 Dec 2019 15:10:48 +0100 Subject: [PATCH 9/9] FileStorage does not support blob settings --- azurerm/resource_arm_storage_account.go | 47 ++++++++++++++++--------- 1 file changed, 30 insertions(+), 17 deletions(-) diff --git a/azurerm/resource_arm_storage_account.go b/azurerm/resource_arm_storage_account.go index a6de74c73631..dea8c0cedb9f 100644 --- a/azurerm/resource_arm_storage_account.go +++ b/azurerm/resource_arm_storage_account.go @@ -781,12 +781,17 @@ func resourceArmStorageAccountCreate(d *schema.ResourceData, meta interface{}) e } if val, ok := d.GetOk("blob_properties"); ok { - blobClient := meta.(*ArmClient).Storage.BlobServicesClient + // FileStorage does not support blob settings + if accountKind != string(storage.FileStorage) { + blobClient := meta.(*ArmClient).Storage.BlobServicesClient - blobProperties := expandBlobProperties(val.([]interface{})) + 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 _, err = blobClient.SetServiceProperties(ctx, resourceGroupName, storageAccountName, blobProperties); err != nil { + return fmt.Errorf("Error updating Azure Storage Account `blob_properties` %q: %+v", storageAccountName, err) + } + } else { + return fmt.Errorf("`blob_properties` aren't supported for File Storage accounts.") } } @@ -997,14 +1002,19 @@ func resourceArmStorageAccountUpdate(d *schema.ResourceData, meta interface{}) e } if d.HasChange("blob_properties") { - blobClient := meta.(*ArmClient).Storage.BlobServicesClient - blobProperties := expandBlobProperties(d.Get("blob_properties").([]interface{})) + // FileStorage does not support blob settings + if accountKind != string(storage.FileStorage) { + 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) - } + 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") + d.SetPartial("blob_properties") + } else { + return fmt.Errorf("`blob_properties` aren't supported for File Storage accounts.") + } } if d.HasChange("queue_properties") { @@ -1211,15 +1221,18 @@ func resourceArmStorageAccountRead(d *schema.ResourceData, meta interface{}) err blobClient := storageClient.BlobServicesClient - blobProps, err := blobClient.GetServiceProperties(ctx, resGroup, name) - if err != nil { - if !utils.ResponseWasNotFound(blobProps.Response) { - return fmt.Errorf("Error reading blob properties for AzureRM Storage Account %q: %+v", name, err) + // FileStorage does not support blob settings + if resp.Kind != storage.FileStorage { + blobProps, err := blobClient.GetServiceProperties(ctx, resGroup, name) + if err != nil { + if !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) + 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)