From d58562e1504398f6eab0f815bde444afc3d7f061 Mon Sep 17 00:00:00 2001 From: tombuildsstuff Date: Sat, 3 Feb 2018 14:37:18 +0000 Subject: [PATCH] New Data Source: `azurerm_storage_account` Fixes #785 Tests pass: ``` $ acctests azurerm TestAccDataSourceAzureRMStorageAccount_ === RUN TestAccDataSourceAzureRMStorageAccount_basic --- PASS: TestAccDataSourceAzureRMStorageAccount_basic (86.65s) PASS ok github.com/terraform-providers/terraform-provider-azurerm/azurerm 86.675s ``` --- azurerm/data_source_storage_account.go | 275 +++++++++++++++++++ azurerm/data_source_storage_account_test.go | 72 +++++ azurerm/provider.go | 1 + azurerm/resource_arm_storage_account.go | 13 - website/azurerm.erb | 4 + website/docs/d/storage_account.html.markdown | 95 +++++++ website/docs/r/storage_account.html.markdown | 2 +- 7 files changed, 448 insertions(+), 14 deletions(-) create mode 100644 azurerm/data_source_storage_account.go create mode 100644 azurerm/data_source_storage_account_test.go create mode 100644 website/docs/d/storage_account.html.markdown diff --git a/azurerm/data_source_storage_account.go b/azurerm/data_source_storage_account.go new file mode 100644 index 000000000000..0077be12bbab --- /dev/null +++ b/azurerm/data_source_storage_account.go @@ -0,0 +1,275 @@ +package azurerm + +import ( + "fmt" + "strings" + + "github.com/hashicorp/terraform/helper/schema" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" +) + +func dataSourceArmStorageAccount() *schema.Resource { + return &schema.Resource{ + Read: dataSourceArmStorageAccountRead, + + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + }, + + "resource_group_name": resourceGroupNameForDataSourceSchema(), + + "location": locationForDataSourceSchema(), + + "account_kind": { + Type: schema.TypeString, + Computed: true, + }, + + "account_tier": { + Type: schema.TypeString, + Computed: true, + }, + + "account_replication_type": { + Type: schema.TypeString, + Computed: true, + }, + + "access_tier": { + Type: schema.TypeString, + Computed: true, + }, + + "account_encryption_source": { + Type: schema.TypeString, + Computed: true, + }, + + "custom_domain": { + Type: schema.TypeList, + Computed: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Computed: true, + }, + }, + }, + }, + + "enable_blob_encryption": { + Type: schema.TypeBool, + Computed: true, + }, + + "enable_file_encryption": { + Type: schema.TypeBool, + Computed: true, + }, + + "enable_https_traffic_only": { + Type: schema.TypeBool, + Computed: true, + }, + + "primary_location": { + Type: schema.TypeString, + Computed: true, + }, + + "secondary_location": { + Type: schema.TypeString, + Computed: true, + }, + + "primary_blob_endpoint": { + Type: schema.TypeString, + Computed: true, + }, + + "secondary_blob_endpoint": { + Type: schema.TypeString, + Computed: true, + }, + + "primary_queue_endpoint": { + Type: schema.TypeString, + Computed: true, + }, + + "secondary_queue_endpoint": { + Type: schema.TypeString, + Computed: true, + }, + + "primary_table_endpoint": { + Type: schema.TypeString, + Computed: true, + }, + + "secondary_table_endpoint": { + Type: schema.TypeString, + Computed: true, + }, + + // NOTE: The API does not appear to expose a secondary file endpoint + "primary_file_endpoint": { + Type: schema.TypeString, + Computed: true, + }, + + "primary_access_key": { + Type: schema.TypeString, + Computed: true, + }, + + "secondary_access_key": { + Type: schema.TypeString, + Computed: true, + }, + + "primary_connection_string": { + Type: schema.TypeString, + Computed: true, + }, + + "secondary_connection_string": { + Type: schema.TypeString, + Computed: true, + }, + + "primary_blob_connection_string": { + Type: schema.TypeString, + Computed: true, + }, + + "secondary_blob_connection_string": { + Type: schema.TypeString, + Computed: true, + }, + + "tags": tagsForDataSourceSchema(), + }, + } + +} + +func dataSourceArmStorageAccountRead(d *schema.ResourceData, meta interface{}) error { + client := meta.(*ArmClient).storageServiceClient + ctx := meta.(*ArmClient).StopContext + endpointSuffix := meta.(*ArmClient).environment.StorageEndpointSuffix + + name := d.Get("name").(string) + resourceGroup := d.Get("resource_group_name").(string) + + resp, err := client.GetProperties(ctx, resourceGroup, name) + if err != nil { + if utils.ResponseWasNotFound(resp.Response) { + d.SetId("") + return nil + } + return fmt.Errorf("Error reading the state of AzureRM Storage Account %q: %+v", name, err) + } + + d.SetId(*resp.ID) + + keys, err := client.ListKeys(ctx, resourceGroup, name) + if err != nil { + return err + } + + accessKeys := *keys.Keys + if location := resp.Location; location != nil { + d.Set("location", azureRMNormalizeLocation(*location)) + } + d.Set("account_kind", resp.Kind) + + if sku := resp.Sku; sku != nil { + d.Set("account_type", sku.Name) + d.Set("account_tier", sku.Tier) + d.Set("account_replication_type", strings.Split(fmt.Sprintf("%v", sku.Name), "_")[1]) + } + + if props := resp.AccountProperties; props != nil { + d.Set("access_tier", props.AccessTier) + d.Set("enable_https_traffic_only", props.EnableHTTPSTrafficOnly) + + if customDomain := props.CustomDomain; customDomain != nil { + if err := d.Set("custom_domain", flattenStorageAccountCustomDomain(customDomain)); err != nil { + return fmt.Errorf("Error flattening `custom_domain`: %+v", err) + } + } + + if encryption := props.Encryption; encryption != nil { + if services := encryption.Services; services != nil { + if blob := services.Blob; blob != nil { + d.Set("enable_blob_encryption", blob.Enabled) + } + if file := services.File; file != nil { + d.Set("enable_file_encryption", file.Enabled) + } + } + d.Set("account_encryption_source", string(encryption.KeySource)) + } + + // Computed + d.Set("primary_location", props.PrimaryLocation) + d.Set("secondary_location", props.SecondaryLocation) + + if len(accessKeys) > 0 { + pcs := fmt.Sprintf("DefaultEndpointsProtocol=https;AccountName=%s;AccountKey=%s;EndpointSuffix=%s", *resp.Name, *accessKeys[0].Value, endpointSuffix) + d.Set("primary_connection_string", pcs) + } + + if len(accessKeys) > 1 { + scs := fmt.Sprintf("DefaultEndpointsProtocol=https;AccountName=%s;AccountKey=%s;EndpointSuffix=%s", *resp.Name, *accessKeys[1].Value, endpointSuffix) + d.Set("secondary_connection_string", scs) + } + + if endpoints := props.PrimaryEndpoints; endpoints != nil { + d.Set("primary_blob_endpoint", endpoints.Blob) + d.Set("primary_queue_endpoint", endpoints.Queue) + d.Set("primary_table_endpoint", endpoints.Table) + d.Set("primary_file_endpoint", endpoints.File) + + pscs := fmt.Sprintf("DefaultEndpointsProtocol=https;BlobEndpoint=%s;AccountName=%s;AccountKey=%s", + *endpoints.Blob, *resp.Name, *accessKeys[0].Value) + d.Set("primary_blob_connection_string", pscs) + } + + if endpoints := props.SecondaryEndpoints; endpoints != nil { + if blob := endpoints.Blob; blob != nil { + d.Set("secondary_blob_endpoint", blob) + sscs := fmt.Sprintf("DefaultEndpointsProtocol=https;BlobEndpoint=%s;AccountName=%s;AccountKey=%s", + *blob, *resp.Name, *accessKeys[1].Value) + d.Set("secondary_blob_connection_string", sscs) + } else { + d.Set("secondary_blob_endpoint", "") + d.Set("secondary_blob_connection_string", "") + } + + if endpoints.Queue != nil { + d.Set("secondary_queue_endpoint", endpoints.Queue) + } else { + d.Set("secondary_queue_endpoint", "") + } + + if endpoints.Table != nil { + d.Set("secondary_table_endpoint", endpoints.Table) + } else { + d.Set("secondary_table_endpoint", "") + } + } + } + + d.Set("primary_access_key", accessKeys[0].Value) + d.Set("secondary_access_key", accessKeys[1].Value) + + flattenAndSetTags(d, resp.Tags) + + return nil +} diff --git a/azurerm/data_source_storage_account_test.go b/azurerm/data_source_storage_account_test.go new file mode 100644 index 000000000000..e33b28e21cbe --- /dev/null +++ b/azurerm/data_source_storage_account_test.go @@ -0,0 +1,72 @@ +package azurerm + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform/helper/acctest" + "github.com/hashicorp/terraform/helper/resource" +) + +func TestAccDataSourceAzureRMStorageAccount_basic(t *testing.T) { + dataSourceName := "data.azurerm_storage_account.test" + ri := acctest.RandInt() + rs := acctest.RandString(4) + location := testLocation() + preConfig := testAccDataSourceAzureRMStorageAccount_basic(ri, rs, location) + config := testAccDataSourceAzureRMStorageAccount_basicWithDataSource(ri, rs, location) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMStorageAccountDestroy, + Steps: []resource.TestStep{ + { + Config: preConfig, + }, + { + Config: config, + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr(dataSourceName, "account_tier", "Standard"), + resource.TestCheckResourceAttr(dataSourceName, "account_replication_type", "LRS"), + resource.TestCheckResourceAttr(dataSourceName, "tags.%", "1"), + resource.TestCheckResourceAttr(dataSourceName, "tags.environment", "production"), + ), + }, + }, + }) +} + +func testAccDataSourceAzureRMStorageAccount_basic(rInt int, rString string, location string) string { + return fmt.Sprintf(` +resource "azurerm_resource_group" "test" { + name = "acctestsa-%d" + location = "%s" +} + +resource "azurerm_storage_account" "test" { + name = "acctestsads%s" + resource_group_name = "${azurerm_resource_group.test.name}" + + location = "${azurerm_resource_group.test.location}" + account_tier = "Standard" + account_replication_type = "LRS" + + tags { + environment = "production" + } +} +`, rInt, location, rString) +} + +func testAccDataSourceAzureRMStorageAccount_basicWithDataSource(rInt int, rString string, location string) string { + config := testAccDataSourceAzureRMStorageAccount_basic(rInt, rString, location) + return fmt.Sprintf(` +%s + +data "azurerm_storage_account" "test" { + name = "${azurerm_storage_account.test.name}" + resource_group_name = "${azurerm_storage_account.test.resource_group_name}" +} +`, config) +} diff --git a/azurerm/provider.go b/azurerm/provider.go index c3a86303384b..b0c2f5283abc 100644 --- a/azurerm/provider.go +++ b/azurerm/provider.go @@ -79,6 +79,7 @@ func Provider() terraform.ResourceProvider { "azurerm_public_ip": dataSourceArmPublicIP(), "azurerm_resource_group": dataSourceArmResourceGroup(), "azurerm_role_definition": dataSourceArmRoleDefinition(), + "azurerm_storage_account": dataSourceArmStorageAccount(), "azurerm_snapshot": dataSourceArmSnapshot(), "azurerm_subnet": dataSourceArmSubnet(), "azurerm_subscription": dataSourceArmSubscription(), diff --git a/azurerm/resource_arm_storage_account.go b/azurerm/resource_arm_storage_account.go index c82144ad81ed..112b09622edc 100644 --- a/azurerm/resource_arm_storage_account.go +++ b/azurerm/resource_arm_storage_account.go @@ -1,14 +1,12 @@ package azurerm import ( - "context" "fmt" "log" "regexp" "strings" "github.com/Azure/azure-sdk-for-go/services/storage/mgmt/2017-06-01/storage" - "github.com/hashicorp/terraform/helper/resource" "github.com/hashicorp/terraform/helper/schema" "github.com/hashicorp/terraform/helper/validation" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" @@ -652,14 +650,3 @@ func validateArmStorageAccountType(v interface{}, k string) (ws []string, es []e es = append(es, fmt.Errorf("Invalid storage account type %q", input)) return } - -func storageAccountStateRefreshFunc(client storage.AccountsClient, ctx context.Context, resourceGroupName string, storageAccountName string) resource.StateRefreshFunc { - return func() (interface{}, string, error) { - res, err := client.GetProperties(ctx, resourceGroupName, storageAccountName) - if err != nil { - return nil, "", fmt.Errorf("Error issuing read request in storageAccountStateRefreshFunc to Azure ARM for Storage Account '%s' (RG: '%s'): %s", storageAccountName, resourceGroupName, err) - } - - return res, string(res.AccountProperties.ProvisioningState), nil - } -} diff --git a/website/azurerm.erb b/website/azurerm.erb index dc5415355a19..dfb6043cc5a5 100644 --- a/website/azurerm.erb +++ b/website/azurerm.erb @@ -75,6 +75,10 @@ azurerm_role_definition + > + azurerm_storage_account + + > azurerm_subscription diff --git a/website/docs/d/storage_account.html.markdown b/website/docs/d/storage_account.html.markdown new file mode 100644 index 000000000000..ee1c5c676720 --- /dev/null +++ b/website/docs/d/storage_account.html.markdown @@ -0,0 +1,95 @@ +--- +layout: "azurerm" +page_title: "Azure Resource Manager: azurerm_storage_account" +sidebar_current: "docs-azurerm-datasource-storage-account" +description: |- + Gets information about the specified Storage Account. + +--- + +# Data Source: azurerm_storage_account + +Gets information about the specified Storage Account. + +## Example Usage + +```hcl +data "azurerm_storage_account" "test" { + name = "packerimages" + resource_group_name = "packer-storage" +} + +output "storage_account_tier" { + value = "${data.azurerm_storage_account.test.account_tier}" +} +``` + +## Argument Reference + +* `name` - (Required) Specifies the name of the Storage Account +* `resource_group_name` - (Required) Specifies the name of the resource group the Storage Account is located in. + +## Attributes Reference + +* `id` - The ID of the Storage Account. + +* `location` - The Azure location where the Storage Account exists + +* `account_kind` - Defines the Kind of account, either `BlobStorage` or `Storage`. + +* `account_tier` - Defines the Tier of this storage account. + +* `account_replication_type` - Defines the type of replication used for this storage account. + +* `access_tier` - Defines the access tier for `BlobStorage` accounts. + +* `enable_blob_encryption` - Are Encryption Services are enabled for Blob storage? See [here](https://azure.microsoft.com/en-us/documentation/articles/storage-service-encryption/) + for more information. + +* `enable_file_encryption` - Are Encryption Services are enabled for File storage? See [here](https://azure.microsoft.com/en-us/documentation/articles/storage-service-encryption/) + for more information. + +* `enable_https_traffic_only` - Is traffic only allowed via HTTPS? See [here](https://docs.microsoft.com/en-us/azure/storage/storage-require-secure-transfer/) + for more information. + +* `account_encryption_source` - The Encryption Source for this Storage Account. + +* `custom_domain` - A `custom_domain` block as documented below. + +* `tags` - A mapping of tags to assigned to the resource. + +* `primary_location` - The primary location of the Storage Account. + +* `secondary_location` - The secondary location of the Storage Account. + +* `primary_blob_endpoint` - The endpoint URL for blob storage in the primary location. + +* `secondary_blob_endpoint` - The endpoint URL for blob storage in the secondary location. + +* `primary_queue_endpoint` - The endpoint URL for queue storage in the primary location. + +* `secondary_queue_endpoint` - The endpoint URL for queue storage in the secondary location. + +* `primary_table_endpoint` - The endpoint URL for table storage in the primary location. + +* `secondary_table_endpoint` - The endpoint URL for table storage in the secondary location. + +* `primary_file_endpoint` - The endpoint URL for file storage in the primary location. + +* `primary_access_key` - The primary access key for the Storage Account. + +* `secondary_access_key` - The secondary access key for the Storage Account. + +* `primary_connection_string` - The connection string associated with the primary location + +* `secondary_connection_string` - The connection string associated with the secondary location + +* `primary_blob_connection_string` - The connection string associated with the primary blob location + +* `secondary_blob_connection_string` - The connection string associated with the secondary blob location + +--- + +* `custom_domain` supports the following: + +* `name` - The Custom Domain Name used for the Storage Account. diff --git a/website/docs/r/storage_account.html.markdown b/website/docs/r/storage_account.html.markdown index 5cae1a39585a..bbd8b7663df0 100644 --- a/website/docs/r/storage_account.html.markdown +++ b/website/docs/r/storage_account.html.markdown @@ -6,7 +6,7 @@ description: |- Create a Azure Storage Account. --- -# azurerm\_storage\_account +# azurerm_storage_account Create an Azure Storage Account.