diff --git a/azurerm/data_source_storage_management_policy.go b/azurerm/data_source_storage_management_policy.go new file mode 100644 index 000000000000..64195abfd924 --- /dev/null +++ b/azurerm/data_source_storage_management_policy.go @@ -0,0 +1,132 @@ +package azurerm + +import ( + "fmt" + + "github.com/hashicorp/terraform/helper/schema" +) + +func dataSourceArmStorageManagementPolicy() *schema.Resource { + return &schema.Resource{ + Read: dataSourceArmStorageManagementPolicyRead, + + Schema: map[string]*schema.Schema{ + "storage_account_id": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + "rule": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Computed: true, + }, + "enabled": { + Type: schema.TypeBool, + Computed: true, + }, + "filters": { + Type: schema.TypeList, + Computed: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "prefix_match": { + Type: schema.TypeSet, + Computed: true, + Elem: &schema.Schema{Type: schema.TypeString}, + Set: schema.HashString, + }, + "blob_types": { + Type: schema.TypeSet, + Computed: true, + Elem: &schema.Schema{Type: schema.TypeString}, + Set: schema.HashString, + }, + }, + }, + }, + "actions": { + Type: schema.TypeList, + Computed: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "base_blob": { + Type: schema.TypeList, + Computed: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "tier_to_cool_after_days_since_modification_greater_than": { + Type: schema.TypeInt, + Computed: true, + }, + "tier_to_archive_after_days_since_modification_greater_than": { + Type: schema.TypeInt, + Computed: true, + }, + "delete_after_days_since_modification_greater_than": { + Type: schema.TypeInt, + Computed: true, + }, + }, + }, + }, + "snapshot": { + Type: schema.TypeList, + Computed: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "delete_after_days_since_creation_greater_than": { + Type: schema.TypeInt, + Computed: true, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + } +} + +func dataSourceArmStorageManagementPolicyRead(d *schema.ResourceData, meta interface{}) error { + client := meta.(*ArmClient).Storage.ManagementPoliciesClient + ctx := meta.(*ArmClient).StopContext + + storageAccountId := d.Get("storage_account_id").(string) + + rid, err := parseAzureResourceID(storageAccountId) + if err != nil { + return err + } + resourceGroupName := rid.ResourceGroup + storageAccountName := rid.Path["storageAccounts"] + + result, err := client.Get(ctx, resourceGroupName, storageAccountName) + if err != nil { + return err + } + d.SetId(*result.ID) + + if result.Policy != nil { + policy := result.Policy + if policy.Rules != nil { + if err := d.Set("rule", flattenStorageManagementPolicyRules(policy.Rules)); err != nil { + return fmt.Errorf("Error flattening `rule`: %+v", err) + } + } + } + + return nil +} diff --git a/azurerm/data_source_storage_management_policy_test.go b/azurerm/data_source_storage_management_policy_test.go new file mode 100644 index 000000000000..8e8354e44679 --- /dev/null +++ b/azurerm/data_source_storage_management_policy_test.go @@ -0,0 +1,92 @@ +package azurerm + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform/helper/acctest" + "github.com/hashicorp/terraform/helper/resource" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/tf" +) + +func TestAccDataSourceAzureRMStorageManagementPolicy_basic(t *testing.T) { + dataSourceName := "data.azurerm_storage_management_policy.testpolicy" + ri := tf.AccRandTimeInt() + + rs := acctest.RandString(4) + location := testLocation() + config := testAccDataSourceAzureRMStorageManagementPolicy_basic(ri, rs, location) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: config, + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr(dataSourceName, "rule.#", "1"), + resource.TestCheckResourceAttr(dataSourceName, "rule.0.name", "rule1"), + resource.TestCheckResourceAttr(dataSourceName, "rule.0.enabled", "true"), + resource.TestCheckResourceAttr(dataSourceName, "rule.0.filters.#", "1"), + resource.TestCheckResourceAttr(dataSourceName, "rule.0.filters.0.prefix_match.#", "1"), + resource.TestCheckResourceAttr(dataSourceName, "rule.0.filters.0.prefix_match.3439697764", "container1/prefix1"), + resource.TestCheckResourceAttr(dataSourceName, "rule.0.filters.0.blob_types.#", "1"), + resource.TestCheckResourceAttr(dataSourceName, "rule.0.filters.0.blob_types.1068358194", "blockBlob"), + resource.TestCheckResourceAttr(dataSourceName, "rule.0.actions.#", "1"), + resource.TestCheckResourceAttr(dataSourceName, "rule.0.actions.0.base_blob.#", "1"), + resource.TestCheckResourceAttr(dataSourceName, "rule.0.actions.0.base_blob.0.tier_to_cool_after_days_since_modification_greater_than", "10"), + resource.TestCheckResourceAttr(dataSourceName, "rule.0.actions.0.base_blob.0.tier_to_archive_after_days_since_modification_greater_than", "50"), + resource.TestCheckResourceAttr(dataSourceName, "rule.0.actions.0.base_blob.0.delete_after_days_since_modification_greater_than", "100"), + resource.TestCheckResourceAttr(dataSourceName, "rule.0.actions.0.snapshot.#", "1"), + resource.TestCheckResourceAttr(dataSourceName, "rule.0.actions.0.snapshot.0.delete_after_days_since_creation_greater_than", "30"), + ), + }, + }, + }) +} + +func testAccDataSourceAzureRMStorageManagementPolicy_basic(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" + account_kind = "BlobStorage" +} + +resource "azurerm_storage_management_policy" "testpolicy" { + storage_account_id = "${azurerm_storage_account.testsa.id}" + + rule { + name = "rule1" + enabled = true + filters { + prefix_match = [ "container1/prefix1" ] + blob_types = [ "blockBlob" ] + } + actions { + base_blob { + tier_to_cool_after_days_since_modification_greater_than = 10 + tier_to_archive_after_days_since_modification_greater_than = 50 + delete_after_days_since_modification_greater_than = 100 + } + snapshot { + delete_after_days_since_creation_greater_than = 30 + } + } + } +} + +data "azurerm_storage_management_policy" "testpolicy" { + storage_account_id = "${azurerm_storage_management_policy.testpolicy.storage_account_id}" +} +`, rInt, location, rString) +} diff --git a/azurerm/internal/services/storage/client.go b/azurerm/internal/services/storage/client.go index 0ff24a80a348..bd1b7a00dacf 100644 --- a/azurerm/internal/services/storage/client.go +++ b/azurerm/internal/services/storage/client.go @@ -20,8 +20,9 @@ import ( ) type Client struct { - AccountsClient *storage.AccountsClient - FileSystemsClient *filesystems.Client + AccountsClient *storage.AccountsClient + FileSystemsClient *filesystems.Client + ManagementPoliciesClient storage.ManagementPoliciesClient environment az.Environment } @@ -33,12 +34,16 @@ func BuildClient(options *common.ClientOptions) *Client { fileSystemsClient := filesystems.NewWithEnvironment(options.Environment) fileSystemsClient.Authorizer = options.StorageAuthorizer + managementPoliciesClient := storage.NewManagementPoliciesClientWithBaseURI(options.ResourceManagerEndpoint, options.SubscriptionId) + options.ConfigureClient(&managementPoliciesClient.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, - environment: options.Environment, + AccountsClient: &accountsClient, + FileSystemsClient: &fileSystemsClient, + ManagementPoliciesClient: managementPoliciesClient, + environment: options.Environment, } } diff --git a/azurerm/provider.go b/azurerm/provider.go index ce8b77927428..4da93102924f 100644 --- a/azurerm/provider.go +++ b/azurerm/provider.go @@ -132,6 +132,7 @@ func Provider() terraform.ResourceProvider { "azurerm_storage_account_blob_container_sas": dataSourceArmStorageAccountBlobContainerSharedAccessSignature(), "azurerm_storage_account_sas": dataSourceArmStorageAccountSharedAccessSignature(), "azurerm_storage_account": dataSourceArmStorageAccount(), + "azurerm_storage_management_policy": dataSourceArmStorageManagementPolicy(), "azurerm_subnet": dataSourceArmSubnet(), "azurerm_subscription": dataSourceArmSubscription(), "azurerm_subscriptions": dataSourceArmSubscriptions(), @@ -416,6 +417,7 @@ func Provider() terraform.ResourceProvider { "azurerm_storage_blob": resourceArmStorageBlob(), "azurerm_storage_container": resourceArmStorageContainer(), "azurerm_storage_data_lake_gen2_filesystem": resourceArmStorageDataLakeGen2FileSystem(), + "azurerm_storage_management_policy": resourceArmStorageManagementPolicy(), "azurerm_storage_queue": resourceArmStorageQueue(), "azurerm_storage_share": resourceArmStorageShare(), "azurerm_storage_share_directory": resourceArmStorageShareDirectory(), diff --git a/azurerm/resource_arm_storage_management_policy.go b/azurerm/resource_arm_storage_management_policy.go new file mode 100644 index 000000000000..9c4c175c9d64 --- /dev/null +++ b/azurerm/resource_arm_storage_management_policy.go @@ -0,0 +1,397 @@ +package azurerm + +import ( + "fmt" + "regexp" + + "github.com/hashicorp/terraform/helper/validation" + + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure" + + "github.com/Azure/azure-sdk-for-go/services/storage/mgmt/2019-04-01/storage" + + "github.com/hashicorp/terraform/helper/schema" +) + +func resourceArmStorageManagementPolicy() *schema.Resource { + return &schema.Resource{ + Create: resourceArmStorageManagementPolicyCreateOrUpdate, + Read: resourceArmStorageManagementPolicyRead, + Update: resourceArmStorageManagementPolicyCreateOrUpdate, + Delete: resourceArmStorageManagementPolicyDelete, + Importer: &schema.ResourceImporter{ + State: schema.ImportStatePassthrough, + }, + + Schema: map[string]*schema.Schema{ + "storage_account_id": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: azure.ValidateResourceID, + }, + "rule": { + Type: schema.TypeList, + Optional: true, + MinItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringMatch( + regexp.MustCompile(`^[a-zA-Z0-9]*$`), + "A rule name can contain any combination of alpha numeric characters.", + ), + }, + "enabled": { + Type: schema.TypeBool, + Required: true, + }, + "filters": { + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "prefix_match": { + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + Set: schema.HashString, + }, + "blob_types": { + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + ValidateFunc: validation.StringInSlice([]string{"blockBlob"}, false), + }, + Set: schema.HashString, + }, + }, + }, + }, + "actions": { + Type: schema.TypeList, + Required: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "base_blob": { + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "tier_to_cool_after_days_since_modification_greater_than": { + Type: schema.TypeInt, + Optional: true, + ValidateFunc: validation.IntAtLeast(0), + }, + "tier_to_archive_after_days_since_modification_greater_than": { + Type: schema.TypeInt, + Optional: true, + ValidateFunc: validation.IntAtLeast(0), + }, + "delete_after_days_since_modification_greater_than": { + Type: schema.TypeInt, + Optional: true, + ValidateFunc: validation.IntAtLeast(0), + }, + }, + }, + }, + "snapshot": { + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "delete_after_days_since_creation_greater_than": { + Type: schema.TypeInt, + Optional: true, + ValidateFunc: validation.IntAtLeast(0), + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + } +} + +func resourceArmStorageManagementPolicyCreateOrUpdate(d *schema.ResourceData, meta interface{}) error { + client := meta.(*ArmClient).Storage.ManagementPoliciesClient + ctx := meta.(*ArmClient).StopContext + + storageAccountId := d.Get("storage_account_id").(string) + + rid, err := parseAzureResourceID(storageAccountId) + if err != nil { + return err + } + resourceGroupName := rid.ResourceGroup + storageAccountName := rid.Path["storageAccounts"] + + name := "default" // The name of the Storage Account Management Policy. It should always be 'default' (from https://docs.microsoft.com/en-us/rest/api/storagerp/managementpolicies/createorupdate) + + parameters := storage.ManagementPolicy{ + Name: &name, + } + + rules := d.Get("rule").([]interface{}) + armRules, err := expandStorageManagementPolicyRules(rules) + if err != nil { + return fmt.Errorf("Error expanding Azure Storage Management Policy Rules %q: %+v", storageAccountId, err) + } + + parameters.ManagementPolicyProperties = &storage.ManagementPolicyProperties{ + Policy: &storage.ManagementPolicySchema{ + Rules: armRules, + }, + } + + result, err := client.CreateOrUpdate(ctx, resourceGroupName, storageAccountName, parameters) + if err != nil { + return fmt.Errorf("Error creating Azure Storage Management Policy %q: %+v", storageAccountId, err) + } + + result, err = client.Get(ctx, resourceGroupName, storageAccountName) + if err != nil { + return fmt.Errorf("Error getting created Azure Storage Management Policy %q: %+v", storageAccountId, err) + } + + d.SetId(*result.ID) + + return resourceArmStorageManagementPolicyRead(d, meta) +} + +func resourceArmStorageManagementPolicyRead(d *schema.ResourceData, meta interface{}) error { + client := meta.(*ArmClient).Storage.ManagementPoliciesClient + ctx := meta.(*ArmClient).StopContext + + id := d.Id() + + rid, err := parseAzureResourceID(id) + if err != nil { + return err + } + resourceGroupName := rid.ResourceGroup + storageAccountName := rid.Path["storageAccounts"] + + result, err := client.Get(ctx, resourceGroupName, storageAccountName) + if err != nil { + return err + } + + storageAccountID := "/subscriptions/" + rid.SubscriptionID + "/resourceGroups/" + rid.ResourceGroup + "/providers/" + rid.Provider + "/storageAccounts/" + storageAccountName + d.Set("storage_account_id", storageAccountID) + + if policy := result.Policy; policy != nil { + policy := result.Policy + if rules := policy.Rules; rules != nil { + if err := d.Set("rule", flattenStorageManagementPolicyRules(policy.Rules)); err != nil { + return fmt.Errorf("Error flattening `rule`: %+v", err) + } + } + } + + return nil +} + +func resourceArmStorageManagementPolicyDelete(d *schema.ResourceData, meta interface{}) error { + client := meta.(*ArmClient).Storage.ManagementPoliciesClient + ctx := meta.(*ArmClient).StopContext + + id := d.Id() + + rid, err := parseAzureResourceID(id) + if err != nil { + return err + } + resourceGroupName := rid.ResourceGroup + storageAccountName := rid.Path["storageAccounts"] + + _, err = client.Delete(ctx, resourceGroupName, storageAccountName) + if err != nil { + return err + } + return nil +} + +func expandStorageManagementPolicyRules(list []interface{}) (*[]storage.ManagementPolicyRule, error) { + result := []storage.ManagementPolicyRule{} + + for _, tempItem := range list { + if tempItem != nil { + item := tempItem.(map[string]interface{}) + policyRule, err := expandStorageManagementPolicyRule(item) + if err != nil { + return nil, err + } + result = append(result, policyRule) + } + } + return &result, nil +} + +func expandStorageManagementPolicyRule(ref map[string]interface{}) (storage.ManagementPolicyRule, error) { + name := ref["name"].(string) + enabled := ref["enabled"].(bool) + typeVal := "Lifecycle" + + definition := storage.ManagementPolicyDefinition{ + Filters: &storage.ManagementPolicyFilter{}, + Actions: &storage.ManagementPolicyAction{}, + } + filtersRef := ref["filters"].([]interface{}) + if len(filtersRef) == 1 { + if filtersRef[0] != nil { + filterRef := filtersRef[0].(map[string]interface{}) + + prefixMatches := []string{} + prefixMatchesRef := filterRef["prefix_match"].(*schema.Set) + if prefixMatchesRef != nil { + for _, prefixMatchRef := range prefixMatchesRef.List() { + prefixMatches = append(prefixMatches, prefixMatchRef.(string)) + } + } + definition.Filters.PrefixMatch = &prefixMatches + + blobTypes := []string{} + blobTypesRef := filterRef["blob_types"].(*schema.Set) + if blobTypesRef != nil { + for _, blobTypeRef := range blobTypesRef.List() { + blobTypes = append(blobTypes, blobTypeRef.(string)) + } + } + definition.Filters.BlobTypes = &blobTypes + } + } + actionsRef := ref["actions"].([]interface{}) + if len(actionsRef) == 1 { + actionRef := actionsRef[0].(map[string]interface{}) + + baseBlobsRef := actionRef["base_blob"].([]interface{}) + if len(baseBlobsRef) == 1 { + baseBlob := &storage.ManagementPolicyBaseBlob{} + baseBlobRef := baseBlobsRef[0].(map[string]interface{}) + if v, ok := baseBlobRef["tier_to_cool_after_days_since_modification_greater_than"]; ok { + v2 := float64(v.(int)) + baseBlob.TierToCool = &storage.DateAfterModification{DaysAfterModificationGreaterThan: &v2} + } + if v, ok := baseBlobRef["tier_to_archive_after_days_since_modification_greater_than"]; ok { + v2 := float64(v.(int)) + baseBlob.TierToArchive = &storage.DateAfterModification{DaysAfterModificationGreaterThan: &v2} + } + if v, ok := baseBlobRef["delete_after_days_since_modification_greater_than"]; ok { + v2 := float64(v.(int)) + baseBlob.Delete = &storage.DateAfterModification{DaysAfterModificationGreaterThan: &v2} + } + definition.Actions.BaseBlob = baseBlob + } + + snapshotRef := actionRef["snapshot"].([]interface{}) + if len(snapshotRef) == 1 { + snapshot := &storage.ManagementPolicySnapShot{} + snapshotRef := snapshotRef[0].(map[string]interface{}) + if v, ok := snapshotRef["delete_after_days_since_creation_greater_than"]; ok { + v2 := float64(v.(int)) + snapshot.Delete = &storage.DateAfterCreation{DaysAfterCreationGreaterThan: &v2} + } + definition.Actions.Snapshot = snapshot + } + } + + rule := storage.ManagementPolicyRule{ + Name: &name, + Enabled: &enabled, + Type: &typeVal, + Definition: &definition, + } + return rule, nil +} + +func flattenStorageManagementPolicyRules(armRules *[]storage.ManagementPolicyRule) []interface{} { + rules := make([]interface{}, 0) + if armRules == nil { + return rules + } + for _, armRule := range *armRules { + rule := make(map[string]interface{}) + + if armRule.Name != nil { + rule["name"] = *armRule.Name + } + if armRule.Enabled != nil { + rule["enabled"] = *armRule.Enabled + } + + armDefinition := armRule.Definition + if armDefinition != nil { + armFilter := armDefinition.Filters + if armFilter != nil { + filter := make(map[string]interface{}) + if armFilter.PrefixMatch != nil { + prefixMatches := make([]interface{}, 0) + for _, armPrefixMatch := range *armFilter.PrefixMatch { + prefixMatches = append(prefixMatches, armPrefixMatch) + } + filter["prefix_match"] = prefixMatches + } + if armFilter.BlobTypes != nil { + blobTypes := make([]interface{}, 0) + for _, armBlobType := range *armFilter.BlobTypes { + blobTypes = append(blobTypes, armBlobType) + } + filter["blob_types"] = blobTypes + } + rule["filters"] = [1]interface{}{filter} + } + + armAction := armDefinition.Actions + if armAction != nil { + action := make(map[string]interface{}) + armActionBaseBlob := armAction.BaseBlob + if armActionBaseBlob != nil { + baseBlob := make(map[string]interface{}) + if armActionBaseBlob.TierToCool != nil && armActionBaseBlob.TierToCool.DaysAfterModificationGreaterThan != nil { + intTemp := int(*armActionBaseBlob.TierToCool.DaysAfterModificationGreaterThan) + baseBlob["tier_to_cool_after_days_since_modification_greater_than"] = intTemp + } + if armActionBaseBlob.TierToArchive != nil && armActionBaseBlob.TierToArchive.DaysAfterModificationGreaterThan != nil { + intTemp := int(*armActionBaseBlob.TierToArchive.DaysAfterModificationGreaterThan) + baseBlob["tier_to_archive_after_days_since_modification_greater_than"] = intTemp + } + if armActionBaseBlob.Delete != nil && armActionBaseBlob.Delete.DaysAfterModificationGreaterThan != nil { + intTemp := int(*armActionBaseBlob.Delete.DaysAfterModificationGreaterThan) + baseBlob["delete_after_days_since_modification_greater_than"] = intTemp + } + action["base_blob"] = [1]interface{}{baseBlob} + } + + armActionSnaphost := armAction.Snapshot + if armActionSnaphost != nil { + snapshot := make(map[string]interface{}) + if armActionSnaphost.Delete != nil && armActionSnaphost.Delete.DaysAfterCreationGreaterThan != nil { + intTemp := int(*armActionSnaphost.Delete.DaysAfterCreationGreaterThan) + snapshot["delete_after_days_since_creation_greater_than"] = intTemp + } + action["snapshot"] = [1]interface{}{snapshot} + } + + rule["actions"] = [1]interface{}{action} + } + } + + rules = append(rules, rule) + } + + return rules +} diff --git a/azurerm/resource_arm_storage_management_policy_test.go b/azurerm/resource_arm_storage_management_policy_test.go new file mode 100644 index 000000000000..9c59745f6889 --- /dev/null +++ b/azurerm/resource_arm_storage_management_policy_test.go @@ -0,0 +1,448 @@ +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" +) + +func TestAccAzureRMStorageManagementPolicy_basic(t *testing.T) { + resourceName := "azurerm_storage_management_policy.testpolicy" + ri := tf.AccRandTimeInt() + rs := acctest.RandString(4) + location := testLocation() + config := testAccAzureRMStorageManagementPolicy_basic(ri, rs, location) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMStorageAccountManagementPolicyDestroy(), + Steps: []resource.TestStep{ + { + Config: config, + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMStorageAccountManagementPolicyExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "rule.#", "1"), + resource.TestCheckResourceAttr(resourceName, "rule.0.name", "rule1"), + resource.TestCheckResourceAttr(resourceName, "rule.0.enabled", "true"), + resource.TestCheckResourceAttr(resourceName, "rule.0.filters.#", "1"), + resource.TestCheckResourceAttr(resourceName, "rule.0.filters.0.prefix_match.#", "1"), + resource.TestCheckResourceAttr(resourceName, "rule.0.filters.0.prefix_match.3439697764", "container1/prefix1"), + resource.TestCheckResourceAttr(resourceName, "rule.0.filters.0.blob_types.#", "1"), + resource.TestCheckResourceAttr(resourceName, "rule.0.filters.0.blob_types.1068358194", "blockBlob"), + resource.TestCheckResourceAttr(resourceName, "rule.0.actions.#", "1"), + resource.TestCheckResourceAttr(resourceName, "rule.0.actions.0.base_blob.#", "1"), + resource.TestCheckResourceAttr(resourceName, "rule.0.actions.0.base_blob.0.tier_to_cool_after_days_since_modification_greater_than", "10"), + resource.TestCheckResourceAttr(resourceName, "rule.0.actions.0.base_blob.0.tier_to_archive_after_days_since_modification_greater_than", "50"), + resource.TestCheckResourceAttr(resourceName, "rule.0.actions.0.base_blob.0.delete_after_days_since_modification_greater_than", "100"), + resource.TestCheckResourceAttr(resourceName, "rule.0.actions.0.snapshot.#", "1"), + resource.TestCheckResourceAttr(resourceName, "rule.0.actions.0.snapshot.0.delete_after_days_since_creation_greater_than", "30"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccAzureRMStorageManagementPolicy_multipleRule(t *testing.T) { + resourceName := "azurerm_storage_management_policy.testpolicy" + ri := tf.AccRandTimeInt() + rs := acctest.RandString(4) + location := testLocation() + config := testAccAzureRMStorageManagementPolicy_multipleRule(ri, rs, location) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMStorageAccountManagementPolicyDestroy(), + Steps: []resource.TestStep{ + { + Config: config, + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMStorageAccountManagementPolicyExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "rule.#", "2"), + + // Rule1 + resource.TestCheckResourceAttr(resourceName, "rule.0.name", "rule1"), + resource.TestCheckResourceAttr(resourceName, "rule.0.enabled", "true"), + resource.TestCheckResourceAttr(resourceName, "rule.0.filters.#", "1"), + resource.TestCheckResourceAttr(resourceName, "rule.0.filters.0.prefix_match.#", "1"), + resource.TestCheckResourceAttr(resourceName, "rule.0.filters.0.prefix_match.3439697764", "container1/prefix1"), + resource.TestCheckResourceAttr(resourceName, "rule.0.filters.0.blob_types.#", "1"), + resource.TestCheckResourceAttr(resourceName, "rule.0.filters.0.blob_types.1068358194", "blockBlob"), + resource.TestCheckResourceAttr(resourceName, "rule.0.actions.#", "1"), + resource.TestCheckResourceAttr(resourceName, "rule.0.actions.0.base_blob.#", "1"), + resource.TestCheckResourceAttr(resourceName, "rule.0.actions.0.base_blob.0.tier_to_cool_after_days_since_modification_greater_than", "10"), + resource.TestCheckResourceAttr(resourceName, "rule.0.actions.0.base_blob.0.tier_to_archive_after_days_since_modification_greater_than", "50"), + resource.TestCheckResourceAttr(resourceName, "rule.0.actions.0.base_blob.0.delete_after_days_since_modification_greater_than", "100"), + resource.TestCheckResourceAttr(resourceName, "rule.0.actions.0.snapshot.#", "1"), + resource.TestCheckResourceAttr(resourceName, "rule.0.actions.0.snapshot.0.delete_after_days_since_creation_greater_than", "30"), + + // Rule2 + resource.TestCheckResourceAttr(resourceName, "rule.1.name", "rule2"), + resource.TestCheckResourceAttr(resourceName, "rule.1.enabled", "false"), + resource.TestCheckResourceAttr(resourceName, "rule.1.filters.#", "1"), + resource.TestCheckResourceAttr(resourceName, "rule.1.filters.0.prefix_match.#", "2"), + resource.TestCheckResourceAttr(resourceName, "rule.1.filters.0.prefix_match.4102595489", "container2/prefix1"), + resource.TestCheckResourceAttr(resourceName, "rule.1.filters.0.prefix_match.1837232667", "container2/prefix2"), + resource.TestCheckResourceAttr(resourceName, "rule.1.filters.0.blob_types.#", "1"), + resource.TestCheckResourceAttr(resourceName, "rule.1.filters.0.blob_types.1068358194", "blockBlob"), + resource.TestCheckResourceAttr(resourceName, "rule.1.actions.#", "1"), + resource.TestCheckResourceAttr(resourceName, "rule.1.actions.0.base_blob.#", "1"), + resource.TestCheckResourceAttr(resourceName, "rule.1.actions.0.base_blob.0.tier_to_cool_after_days_since_modification_greater_than", "11"), + resource.TestCheckResourceAttr(resourceName, "rule.1.actions.0.base_blob.0.tier_to_archive_after_days_since_modification_greater_than", "51"), + resource.TestCheckResourceAttr(resourceName, "rule.1.actions.0.base_blob.0.delete_after_days_since_modification_greater_than", "101"), + resource.TestCheckResourceAttr(resourceName, "rule.1.actions.0.snapshot.#", "1"), + resource.TestCheckResourceAttr(resourceName, "rule.1.actions.0.snapshot.0.delete_after_days_since_creation_greater_than", "31"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccAzureRMStorageManagementPolicy_updateMultipleRule(t *testing.T) { + resourceName := "azurerm_storage_management_policy.testpolicy" + ri := tf.AccRandTimeInt() + rs := acctest.RandString(4) + location := testLocation() + config1 := testAccAzureRMStorageManagementPolicy_multipleRule(ri, rs, location) + config2 := testAccAzureRMStorageManagementPolicy_multipleRuleUpdated(ri, rs, location) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMStorageAccountManagementPolicyDestroy(), + Steps: []resource.TestStep{ + { + Config: config1, + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMStorageAccountManagementPolicyExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "rule.#", "2"), + + // Rule1 + resource.TestCheckResourceAttr(resourceName, "rule.0.name", "rule1"), + resource.TestCheckResourceAttr(resourceName, "rule.0.enabled", "true"), + resource.TestCheckResourceAttr(resourceName, "rule.0.filters.#", "1"), + resource.TestCheckResourceAttr(resourceName, "rule.0.filters.0.prefix_match.#", "1"), + resource.TestCheckResourceAttr(resourceName, "rule.0.filters.0.prefix_match.3439697764", "container1/prefix1"), + resource.TestCheckResourceAttr(resourceName, "rule.0.filters.0.blob_types.#", "1"), + resource.TestCheckResourceAttr(resourceName, "rule.0.filters.0.blob_types.1068358194", "blockBlob"), + resource.TestCheckResourceAttr(resourceName, "rule.0.actions.#", "1"), + resource.TestCheckResourceAttr(resourceName, "rule.0.actions.0.base_blob.#", "1"), + resource.TestCheckResourceAttr(resourceName, "rule.0.actions.0.base_blob.0.tier_to_cool_after_days_since_modification_greater_than", "10"), + resource.TestCheckResourceAttr(resourceName, "rule.0.actions.0.base_blob.0.tier_to_archive_after_days_since_modification_greater_than", "50"), + resource.TestCheckResourceAttr(resourceName, "rule.0.actions.0.base_blob.0.delete_after_days_since_modification_greater_than", "100"), + resource.TestCheckResourceAttr(resourceName, "rule.0.actions.0.snapshot.#", "1"), + resource.TestCheckResourceAttr(resourceName, "rule.0.actions.0.snapshot.0.delete_after_days_since_creation_greater_than", "30"), + + // Rule2 + resource.TestCheckResourceAttr(resourceName, "rule.1.name", "rule2"), + resource.TestCheckResourceAttr(resourceName, "rule.1.enabled", "false"), + resource.TestCheckResourceAttr(resourceName, "rule.1.filters.#", "1"), + resource.TestCheckResourceAttr(resourceName, "rule.1.filters.0.prefix_match.#", "2"), + resource.TestCheckResourceAttr(resourceName, "rule.1.filters.0.prefix_match.4102595489", "container2/prefix1"), + resource.TestCheckResourceAttr(resourceName, "rule.1.filters.0.prefix_match.1837232667", "container2/prefix2"), + resource.TestCheckResourceAttr(resourceName, "rule.1.filters.0.blob_types.#", "1"), + resource.TestCheckResourceAttr(resourceName, "rule.1.filters.0.blob_types.1068358194", "blockBlob"), + resource.TestCheckResourceAttr(resourceName, "rule.1.actions.#", "1"), + resource.TestCheckResourceAttr(resourceName, "rule.1.actions.0.base_blob.#", "1"), + resource.TestCheckResourceAttr(resourceName, "rule.1.actions.0.base_blob.0.tier_to_cool_after_days_since_modification_greater_than", "11"), + resource.TestCheckResourceAttr(resourceName, "rule.1.actions.0.base_blob.0.tier_to_archive_after_days_since_modification_greater_than", "51"), + resource.TestCheckResourceAttr(resourceName, "rule.1.actions.0.base_blob.0.delete_after_days_since_modification_greater_than", "101"), + resource.TestCheckResourceAttr(resourceName, "rule.1.actions.0.snapshot.#", "1"), + resource.TestCheckResourceAttr(resourceName, "rule.1.actions.0.snapshot.0.delete_after_days_since_creation_greater_than", "31"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + { + Config: config2, + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMStorageAccountManagementPolicyExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "rule.#", "2"), + + // Rule1 + resource.TestCheckResourceAttr(resourceName, "rule.0.name", "rule1"), + resource.TestCheckResourceAttr(resourceName, "rule.0.enabled", "true"), + resource.TestCheckResourceAttr(resourceName, "rule.0.filters.#", "1"), + resource.TestCheckResourceAttr(resourceName, "rule.0.filters.0.prefix_match.#", "1"), + resource.TestCheckResourceAttr(resourceName, "rule.0.filters.0.prefix_match.3439697764", "container1/prefix1"), + resource.TestCheckResourceAttr(resourceName, "rule.0.filters.0.blob_types.#", "1"), + resource.TestCheckResourceAttr(resourceName, "rule.0.filters.0.blob_types.1068358194", "blockBlob"), + resource.TestCheckResourceAttr(resourceName, "rule.0.actions.#", "1"), + resource.TestCheckResourceAttr(resourceName, "rule.0.actions.0.base_blob.#", "1"), + resource.TestCheckResourceAttr(resourceName, "rule.0.actions.0.base_blob.0.tier_to_cool_after_days_since_modification_greater_than", "10"), + resource.TestCheckResourceAttr(resourceName, "rule.0.actions.0.base_blob.0.tier_to_archive_after_days_since_modification_greater_than", "50"), + resource.TestCheckResourceAttr(resourceName, "rule.0.actions.0.base_blob.0.delete_after_days_since_modification_greater_than", "100"), + resource.TestCheckResourceAttr(resourceName, "rule.0.actions.0.snapshot.#", "1"), + resource.TestCheckResourceAttr(resourceName, "rule.0.actions.0.snapshot.0.delete_after_days_since_creation_greater_than", "30"), + + // Rule2 + resource.TestCheckResourceAttr(resourceName, "rule.1.name", "rule2"), + resource.TestCheckResourceAttr(resourceName, "rule.1.enabled", "true"), // check updated + resource.TestCheckResourceAttr(resourceName, "rule.1.filters.#", "1"), + resource.TestCheckResourceAttr(resourceName, "rule.1.filters.0.prefix_match.#", "2"), + resource.TestCheckResourceAttr(resourceName, "rule.1.filters.0.prefix_match.4102595489", "container2/prefix1"), + resource.TestCheckResourceAttr(resourceName, "rule.1.filters.0.prefix_match.1837232667", "container2/prefix2"), + resource.TestCheckResourceAttr(resourceName, "rule.1.filters.0.blob_types.#", "1"), + resource.TestCheckResourceAttr(resourceName, "rule.1.filters.0.blob_types.1068358194", "blockBlob"), + resource.TestCheckResourceAttr(resourceName, "rule.1.actions.#", "1"), + resource.TestCheckResourceAttr(resourceName, "rule.1.actions.0.base_blob.#", "1"), + resource.TestCheckResourceAttr(resourceName, "rule.1.actions.0.base_blob.0.tier_to_cool_after_days_since_modification_greater_than", "12"), // check updated + resource.TestCheckResourceAttr(resourceName, "rule.1.actions.0.base_blob.0.tier_to_archive_after_days_since_modification_greater_than", "52"), // check updated + resource.TestCheckResourceAttr(resourceName, "rule.1.actions.0.base_blob.0.delete_after_days_since_modification_greater_than", "102"), // check updated + resource.TestCheckResourceAttr(resourceName, "rule.1.actions.0.snapshot.#", "1"), + resource.TestCheckResourceAttr(resourceName, "rule.1.actions.0.snapshot.0.delete_after_days_since_creation_greater_than", "32"), // check updated + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func testCheckAzureRMStorageAccountManagementPolicyDestroy() resource.TestCheckFunc { + return func(s *terraform.State) error { + for _, rs := range s.RootModule().Resources { + if rs.Type != "azurerm_storage_management_policy" { + continue + } + storageAccountID := rs.Primary.Attributes["storage_account_id"] + + exists, err := testCheckAzureRMStorageAccountManagementPolicyExistsInternal(storageAccountID) + if err != nil { + return fmt.Errorf("Error checking if item has been destroyed: %s", err) + } + if exists { + return fmt.Errorf("Bad: Storage Account Management Policy '%q' still exists", storageAccountID) + } + } + + return nil + } +} + +func testCheckAzureRMStorageAccountManagementPolicyExists(resourceName string) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[resourceName] + if !ok { + return fmt.Errorf("Not found: %s", resourceName) + } + storageAccountID := rs.Primary.Attributes["storage_account_id"] + + exists, err := testCheckAzureRMStorageAccountManagementPolicyExistsInternal(storageAccountID) + if err != nil { + return fmt.Errorf("Error checking if item exists: %s", err) + } + if !exists { + return fmt.Errorf("Bad: Storage Account Management Policy '%q' does not exist", storageAccountID) + } + + return nil + } +} + +func testCheckAzureRMStorageAccountManagementPolicyExistsInternal(storageAccountID string) (bool, error) { + rid, err := parseAzureResourceID(storageAccountID) + if err != nil { + return false, fmt.Errorf("Bad: Failed to parse ID (id: %s): %+v", storageAccountID, err) + } + + resourceGroupName := rid.ResourceGroup + storageAccountName := rid.Path["storageAccounts"] + + conn := testAccProvider.Meta().(*ArmClient).Storage.ManagementPoliciesClient + ctx := testAccProvider.Meta().(*ArmClient).StopContext + + response, err := conn.Get(ctx, resourceGroupName, storageAccountName) + if err != nil { + if response.Response.IsHTTPStatus(404) { + return false, nil + } + return false, fmt.Errorf("Bad: Get on storageAccount ManagementPolicy client (id: %s): %+v", storageAccountID, err) + } + + return true, nil +} + +func testAccAzureRMStorageManagementPolicy_basic(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" + account_kind = "BlobStorage" +} + +resource "azurerm_storage_management_policy" "testpolicy" { + storage_account_id = "${azurerm_storage_account.testsa.id}" + + rule { + name = "rule1" + enabled = true + filters { + prefix_match = [ "container1/prefix1" ] + blob_types = [ "blockBlob" ] + } + actions { + base_blob { + tier_to_cool_after_days_since_modification_greater_than = 10 + tier_to_archive_after_days_since_modification_greater_than = 50 + delete_after_days_since_modification_greater_than = 100 + } + snapshot { + delete_after_days_since_creation_greater_than = 30 + } + } + } +} +`, rInt, location, rString) +} + +func testAccAzureRMStorageManagementPolicy_multipleRule(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" + account_kind = "BlobStorage" +} + +resource "azurerm_storage_management_policy" "testpolicy" { + storage_account_id = "${azurerm_storage_account.testsa.id}" + + rule { + name = "rule1" + enabled = true + filters { + prefix_match = [ "container1/prefix1" ] + blob_types = [ "blockBlob" ] + } + actions { + base_blob { + tier_to_cool_after_days_since_modification_greater_than = 10 + tier_to_archive_after_days_since_modification_greater_than = 50 + delete_after_days_since_modification_greater_than = 100 + } + snapshot { + delete_after_days_since_creation_greater_than = 30 + } + } + } + rule { + name = "rule2" + enabled = false + filters { + prefix_match = [ "container2/prefix1", "container2/prefix2" ] + blob_types = [ "blockBlob" ] + } + actions { + base_blob { + tier_to_cool_after_days_since_modification_greater_than = 11 + tier_to_archive_after_days_since_modification_greater_than = 51 + delete_after_days_since_modification_greater_than = 101 + } + snapshot { + delete_after_days_since_creation_greater_than = 31 + } + } + } +} +`, rInt, location, rString) +} + +func testAccAzureRMStorageManagementPolicy_multipleRuleUpdated(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" + account_kind = "BlobStorage" +} + +resource "azurerm_storage_management_policy" "testpolicy" { + storage_account_id = "${azurerm_storage_account.testsa.id}" + + rule { + name = "rule1" + enabled = true + filters { + prefix_match = [ "container1/prefix1" ] + blob_types = [ "blockBlob" ] + } + actions { + base_blob { + tier_to_cool_after_days_since_modification_greater_than = 10 + tier_to_archive_after_days_since_modification_greater_than = 50 + delete_after_days_since_modification_greater_than = 100 + } + snapshot { + delete_after_days_since_creation_greater_than = 30 + } + } + } + rule { + name = "rule2" + enabled = true + filters { + prefix_match = [ "container2/prefix1", "container2/prefix2" ] + blob_types = [ "blockBlob" ] + } + actions { + base_blob { + tier_to_cool_after_days_since_modification_greater_than = 12 + tier_to_archive_after_days_since_modification_greater_than = 52 + delete_after_days_since_modification_greater_than = 102 + } + snapshot { + delete_after_days_since_creation_greater_than = 32 + } + } + } +} +`, rInt, location, rString) +} diff --git a/website/azurerm.erb b/website/azurerm.erb index b18a292c7a31..64075b2cf352 100644 --- a/website/azurerm.erb +++ b/website/azurerm.erb @@ -350,6 +350,10 @@ azurerm_storage_account_sas +
  • + azurerm_storage_management_policy +
  • +
  • azurerm_subnet
  • @@ -1746,6 +1750,10 @@ azurerm_storage_data_lake_gen2_filesystem +
  • + azurerm_storage_management_policy +
  • +
  • azurerm_storage_queue
  • diff --git a/website/docs/d/storage_management_policy.html.markdown b/website/docs/d/storage_management_policy.html.markdown new file mode 100644 index 000000000000..c2c716eeb602 --- /dev/null +++ b/website/docs/d/storage_management_policy.html.markdown @@ -0,0 +1,72 @@ +--- +layout: "azurerm" +page_title: "Azure Resource Manager: azurerm_storage_management_policy" +sidebar_current: "docs-azurerm-datasource-storage-management-policy" +description: |- + Gets information about an existing Storage Management Policy. +--- + +# Data Source: azurerm_storage_management_policy + +Use this data source to access information about an existing Storage Management Policy. + +## Example Usage + +```terraform +data "azurerm_storage_account" "test" { + name = "storageaccountname" + resource_group_name = "resourcegroupname" +} + +data "azurerm_storage_management_policy" "testpolicy" { + storage_account_id = "${azurerm_storage_account.test.id}" +} +``` + +## Argument Reference + +The following arguments are supported: + +* `storage_account_id` - (Required) Specifies the id of the storage account to retrieve the management policy for. + +## Attributes Reference + +* `id` - The ID of the Management Policy. +* `rule` - A `rule` block as documented below. + +--- + +* `rule` supports the following: + +* `name` - (Required) A rule name can contain any combination of alpha numeric characters. Rule name is case-sensitive. It must be unique within a policy. +* `enabled` - (Required) Boolean to specify whether the rule is enabled. +* `filters` - A `filter` block as documented below. +* `actions` - An `actions` block as documented below. + +--- + +`filters` supports the following: + +* `prefix_match` - An array of strings for prefixes to be matched. +* `blob_types` - An array of predefined values. Only `blockBlob` is supported. + +--- + +`actions` supports the following: + +* `base_blob` - A `base_blob` block as documented below. +* `snapshot` - A `snapshot` block as documented below. + +--- + +`base_blob` supports the following: + +* `tier_to_cool_after_days_since_modification_greater_than` - The age in days after last modification to tier blobs to cool storage. Supports blob currently at Hot tier. +* `tier_to_archive_after_days_since_modification_greater_than` - The age in days after last modification to tier blobs to archive storage. Supports blob currently at Hot or Cool tier. +* `delete_after_days_since_modification_greater_than` - The age in days after last modification to delete the blob. + +--- + +`snapshot` supports the following: + +* `delete_after_days_since_creation_greater_than` - The age in days after create to delete the snaphot. diff --git a/website/docs/r/storage_management_policy.html.markdown b/website/docs/r/storage_management_policy.html.markdown new file mode 100644 index 000000000000..0d4ccba3f301 --- /dev/null +++ b/website/docs/r/storage_management_policy.html.markdown @@ -0,0 +1,130 @@ +--- +layout: "azurerm" +page_title: "Azure Resource Manager: azurerm_storage_management_policy" +sidebar_current: "docs-azurerm-resource-storage-management-policy" +description: |- + Manages an Azure Storage Account Management Policy. +--- + +# azurerm_storage_management_policy + +Manages an Azure Storage Account Management Policy. + +## 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 = "${azurerm_resource_group.testrg.location}" + account_tier = "Standard" + account_replication_type = "LRS" + account_kind = "BlobStorage" +} + +resource "azurerm_storage_management_policy" "testpolicy" { + storage_account_id = "${azurerm_storage_account.testsa.id}" + + rule { + name = "rule1" + enabled = true + filters { + prefix_match = [ "container1/prefix1" ] + blob_types = [ "blockBlob" ] + } + actions { + base_blob { + tier_to_cool_after_days_since_modification_greater_than = 10 + tier_to_archive_after_days_since_modification_greater_than = 50 + delete_after_days_since_modification_greater_than = 100 + } + snapshot { + delete_after_days_since_creation_greater_than = 30 + } + } + } + rule { + name = "rule2" + enabled = false + filters { + prefix_match = [ "container2/prefix1", "container2/prefix2" ] + blob_types = [ "blockBlob" ] + } + actions { + base_blob { + tier_to_cool_after_days_since_modification_greater_than = 11 + tier_to_archive_after_days_since_modification_greater_than = 51 + delete_after_days_since_modification_greater_than = 101 + } + snapshot { + delete_after_days_since_creation_greater_than = 31 + } + } + } +} +``` + +## Argument Reference + +The following arguments are supported: + +* `storage_account_id` - (Required) Specifies the id of the storage account to apply the management policy to. + +* `rule` - (Optional) A `rule` block as documented below. + +--- + +* `rule` supports the following: + +* `name` - (Required) A rule name can contain any combination of alpha numeric characters. Rule name is case-sensitive. It must be unique within a policy. +* `enabled` - (Required) Boolean to specify whether the rule is enabled. +* `filters` - A `filter` block as documented below. +* `actions` - An `actions` block as documented below. + +--- + +`filters` supports the following: + +* `prefix_match` - An array of strings for prefixes to be matched. +* `blob_types` - An array of predefined values. Only `blockBlob` is supported. + +--- + +`actions` supports the following: + +* `base_blob` - A `base_blob` block as documented below. +* `snapshot` - A `snapshot` block as documented below. + +--- + +`base_blob` supports the following: + +* `tier_to_cool_after_days_since_modification_greater_than` - The age in days after last modification to tier blobs to cool storage. Supports blob currently at Hot tier. Must be at least 0. +* `tier_to_archive_after_days_since_modification_greater_than` - The age in days after last modification to tier blobs to archive storage. Supports blob currently at Hot or Cool tier. Must be at least 0. +* `delete_after_days_since_modification_greater_than` - The age in days after last modification to delete the blob. Must be at least 0. + +--- + +`snapshot` supports the following: + +* `delete_after_days_since_creation_greater_than` - The age in days after create to delete the snaphot. Must be at least 0. + +## Attributes Reference + +The following attributes are exported: + +* `id` - The ID of the Storage Account Management Policy. + +## Import + +Storage Account Management Policies can be imported using the `resource id`, e.g. + +```shell +terraform import azurerm_storage_management_policy.test /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/mygroup1/providers/Microsoft.Storage/storageAccounts/myaccountname/managementPoliices/default +```