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 +