diff --git a/builtin/providers/azurerm/provider.go b/builtin/providers/azurerm/provider.go index 4cbc4b4f4..de93f31f3 100644 --- a/builtin/providers/azurerm/provider.go +++ b/builtin/providers/azurerm/provider.go @@ -55,8 +55,8 @@ func Provider() terraform.ResourceProvider { "azurerm_public_ip": resourceArmPublicIp(), //"azurerm_route": resourceArmRoute(), //"azurerm_route_table": resourceArmRouteTable(), - //"azurerm_storage_account": resourceArmStorageAccount(), - "azurerm_storage_blob": resourceArmStorageBlob(), + "azurerm_storage_account": resourceArmStorageAccount(), + "azurerm_storage_blob": resourceArmStorageBlob(), //"azurerm_storage_container": resourceArmStorageContainer(), "azurerm_storage_queue": resourceArmStorageQueue(), "azurerm_subnet": resourceArmSubnet(), diff --git a/builtin/providers/azurerm/resource_arm_storage_account.go b/builtin/providers/azurerm/resource_arm_storage_account.go index 059e9165e..2a075529c 100644 --- a/builtin/providers/azurerm/resource_arm_storage_account.go +++ b/builtin/providers/azurerm/resource_arm_storage_account.go @@ -1,309 +1,297 @@ package azurerm -//import ( -// "fmt" -// "net/http" -// "regexp" -// "strings" -// -// "github.com/Azure/azure-sdk-for-go/arm/storage" -// "github.com/hashicorp/terraform/helper/schema" -//) -// -//func resourceArmStorageAccount() *schema.Resource { -// return &schema.Resource{ -// Create: resourceArmStorageAccountCreate, -// Read: resourceArmStorageAccountRead, -// Update: resourceArmStorageAccountUpdate, -// Delete: resourceArmStorageAccountDelete, -// -// Schema: map[string]*schema.Schema{ -// "name": &schema.Schema{ -// Type: schema.TypeString, -// Required: true, -// ForceNew: true, -// ValidateFunc: validateArmStorageAccountName, -// }, -// -// "resource_group_name": &schema.Schema{ -// Type: schema.TypeString, -// Required: true, -// ForceNew: true, -// }, -// -// "location": &schema.Schema{ -// Type: schema.TypeString, -// Required: true, -// ForceNew: true, -// StateFunc: azureRMNormalizeLocation, -// }, -// -// "account_type": &schema.Schema{ -// Type: schema.TypeString, -// Required: true, -// ValidateFunc: validateArmStorageAccountType, -// }, -// -// "primary_location": &schema.Schema{ -// Type: schema.TypeString, -// Computed: true, -// }, -// -// "secondary_location": &schema.Schema{ -// Type: schema.TypeString, -// Computed: true, -// }, -// -// "primary_blob_endpoint": &schema.Schema{ -// Type: schema.TypeString, -// Computed: true, -// }, -// -// "secondary_blob_endpoint": &schema.Schema{ -// Type: schema.TypeString, -// Computed: true, -// }, -// -// "primary_queue_endpoint": &schema.Schema{ -// Type: schema.TypeString, -// Computed: true, -// }, -// -// "secondary_queue_endpoint": &schema.Schema{ -// Type: schema.TypeString, -// Computed: true, -// }, -// -// "primary_table_endpoint": &schema.Schema{ -// Type: schema.TypeString, -// Computed: true, -// }, -// -// "secondary_table_endpoint": &schema.Schema{ -// Type: schema.TypeString, -// Computed: true, -// }, -// -// // NOTE: The API does not appear to expose a secondary file endpoint -// "primary_file_endpoint": &schema.Schema{ -// Type: schema.TypeString, -// Computed: true, -// }, -// -// "primary_access_key": &schema.Schema{ -// Type: schema.TypeString, -// Computed: true, -// }, -// -// "secondary_access_key": &schema.Schema{ -// Type: schema.TypeString, -// Computed: true, -// }, -// -// "tags": tagsSchema(), -// }, -// } -//} -// -//func resourceArmStorageAccountCreate(d *schema.ResourceData, meta interface{}) error { -// client := meta.(*ArmClient).storageServiceClient -// -// resourceGroupName := d.Get("resource_group_name").(string) -// storageAccountName := d.Get("name").(string) -// accountType := d.Get("account_type").(string) -// location := d.Get("location").(string) -// tags := d.Get("tags").(map[string]interface{}) -// -// opts := storage.AccountCreateParameters{ -// Location: &location, -// Properties: &storage.AccountPropertiesCreateParameters{ -// AccountType: storage.AccountType(accountType), -// }, -// Tags: expandTags(tags), -// } -// -// accResp, err := client.Create(resourceGroupName, storageAccountName, opts) -// if err != nil { -// return fmt.Errorf("Error creating Azure Storage Account '%s': %s", storageAccountName, err) -// } -// _, err = pollIndefinitelyAsNeeded(client.Client, accResp.Response.Response, http.StatusOK) -// if err != nil { -// return fmt.Errorf("Error creating Azure Storage Account %q: %s", storageAccountName, err) -// } -// -// // The only way to get the ID back apparently is to read the resource again -// account, err := client.GetProperties(resourceGroupName, storageAccountName) -// if err != nil { -// return fmt.Errorf("Error retrieving Azure Storage Account %q: %s", storageAccountName, err) -// } -// -// d.SetId(*account.ID) -// -// return resourceArmStorageAccountRead(d, meta) -//} -// -//// resourceArmStorageAccountUpdate is unusual in the ARM API where most resources have a combined -//// and idempotent operation for CreateOrUpdate. In particular updating all of the parameters -//// available requires a call to Update per parameter... -//func resourceArmStorageAccountUpdate(d *schema.ResourceData, meta interface{}) error { -// client := meta.(*ArmClient).storageServiceClient -// id, err := parseAzureResourceID(d.Id()) -// if err != nil { -// return err -// } -// storageAccountName := id.Path["storageAccounts"] -// resourceGroupName := id.ResourceGroup -// -// d.Partial(true) -// -// if d.HasChange("account_type") { -// accountType := d.Get("account_type").(string) -// -// opts := storage.AccountUpdateParameters{ -// Properties: &storage.AccountPropertiesUpdateParameters{ -// AccountType: storage.AccountType(accountType), -// }, -// } -// accResp, err := client.Update(resourceGroupName, storageAccountName, opts) -// if err != nil { -// return fmt.Errorf("Error updating Azure Storage Account type %q: %s", storageAccountName, err) -// } -// _, err = pollIndefinitelyAsNeeded(client.Client, accResp.Response.Response, http.StatusOK) -// if err != nil { -// return fmt.Errorf("Error updating Azure Storage Account type %q: %s", storageAccountName, err) -// } -// -// d.SetPartial("account_type") -// } -// -// if d.HasChange("tags") { -// tags := d.Get("tags").(map[string]interface{}) -// -// opts := storage.AccountUpdateParameters{ -// Tags: expandTags(tags), -// } -// accResp, err := client.Update(resourceGroupName, storageAccountName, opts) -// if err != nil { -// return fmt.Errorf("Error updating Azure Storage Account tags %q: %s", storageAccountName, err) -// } -// _, err = pollIndefinitelyAsNeeded(client.Client, accResp.Response.Response, http.StatusOK) -// if err != nil { -// return fmt.Errorf("Error updating Azure Storage Account tags %q: %s", storageAccountName, err) -// } -// -// d.SetPartial("tags") -// } -// -// d.Partial(false) -// return nil -//} -// -//func resourceArmStorageAccountRead(d *schema.ResourceData, meta interface{}) error { -// client := meta.(*ArmClient).storageServiceClient -// -// id, err := parseAzureResourceID(d.Id()) -// if err != nil { -// return err -// } -// name := id.Path["storageAccounts"] -// resGroup := id.ResourceGroup -// -// resp, err := client.GetProperties(resGroup, name) -// if err != nil { -// if resp.StatusCode == http.StatusNotFound { -// d.SetId("") -// return nil -// } -// -// return fmt.Errorf("Error reading the state of AzureRM Storage Account %q: %s", name, err) -// } -// -// keys, err := client.ListKeys(resGroup, name) -// if err != nil { -// return err -// } -// -// d.Set("primary_access_key", keys.Key1) -// d.Set("secondary_access_key", keys.Key2) -// d.Set("location", resp.Location) -// d.Set("account_type", resp.Properties.AccountType) -// d.Set("primary_location", resp.Properties.PrimaryLocation) -// d.Set("secondary_location", resp.Properties.SecondaryLocation) -// -// if resp.Properties.PrimaryEndpoints != nil { -// d.Set("primary_blob_endpoint", resp.Properties.PrimaryEndpoints.Blob) -// d.Set("primary_queue_endpoint", resp.Properties.PrimaryEndpoints.Queue) -// d.Set("primary_table_endpoint", resp.Properties.PrimaryEndpoints.Table) -// d.Set("primary_file_endpoint", resp.Properties.PrimaryEndpoints.File) -// } -// -// if resp.Properties.SecondaryEndpoints != nil { -// if resp.Properties.SecondaryEndpoints.Blob != nil { -// d.Set("secondary_blob_endpoint", resp.Properties.SecondaryEndpoints.Blob) -// } else { -// d.Set("secondary_blob_endpoint", "") -// } -// if resp.Properties.SecondaryEndpoints.Queue != nil { -// d.Set("secondary_queue_endpoint", resp.Properties.SecondaryEndpoints.Queue) -// } else { -// d.Set("secondary_queue_endpoint", "") -// } -// if resp.Properties.SecondaryEndpoints.Table != nil { -// d.Set("secondary_table_endpoint", resp.Properties.SecondaryEndpoints.Table) -// } else { -// d.Set("secondary_table_endpoint", "") -// } -// } -// -// flattenAndSetTags(d, resp.Tags) -// -// return nil -//} -// -//func resourceArmStorageAccountDelete(d *schema.ResourceData, meta interface{}) error { -// client := meta.(*ArmClient).storageServiceClient -// -// id, err := parseAzureResourceID(d.Id()) -// if err != nil { -// return err -// } -// name := id.Path["storageAccounts"] -// resGroup := id.ResourceGroup -// -// accResp, err := client.Delete(resGroup, name) -// if err != nil { -// return fmt.Errorf("Error issuing AzureRM delete request for storage account %q: %s", name, err) -// } -// _, err = pollIndefinitelyAsNeeded(client.Client, accResp.Response, http.StatusNotFound) -// if err != nil { -// return fmt.Errorf("Error polling for AzureRM delete request for storage account %q: %s", name, err) -// } -// -// return nil -//} -// -//func validateArmStorageAccountName(v interface{}, k string) (ws []string, es []error) { -// input := v.(string) -// -// if !regexp.MustCompile(`\A([a-z0-9]{3,24})\z`).MatchString(input) { -// es = append(es, fmt.Errorf("name can only consist of lowercase letters and numbers, and must be between 3 and 24 characters long")) -// } -// -// return -//} -// -//func validateArmStorageAccountType(v interface{}, k string) (ws []string, es []error) { -// validAccountTypes := []string{"standard_lrs", "standard_zrs", -// "standard_grs", "standard_ragrs", "premium_lrs"} -// -// input := strings.ToLower(v.(string)) -// -// for _, valid := range validAccountTypes { -// if valid == input { -// return -// } -// } -// -// es = append(es, fmt.Errorf("Invalid storage account type %q", input)) -// return -//} +import ( + "fmt" + "net/http" + "regexp" + "strings" + + "github.com/Azure/azure-sdk-for-go/arm/storage" + "github.com/hashicorp/terraform/helper/schema" +) + +func resourceArmStorageAccount() *schema.Resource { + return &schema.Resource{ + Create: resourceArmStorageAccountCreate, + Read: resourceArmStorageAccountRead, + Update: resourceArmStorageAccountUpdate, + Delete: resourceArmStorageAccountDelete, + + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validateArmStorageAccountName, + }, + + "resource_group_name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + + "location": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + StateFunc: azureRMNormalizeLocation, + }, + + "account_type": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validateArmStorageAccountType, + }, + + "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, + }, + + "tags": tagsSchema(), + }, + } +} + +func resourceArmStorageAccountCreate(d *schema.ResourceData, meta interface{}) error { + client := meta.(*ArmClient).storageServiceClient + + resourceGroupName := d.Get("resource_group_name").(string) + storageAccountName := d.Get("name").(string) + accountType := d.Get("account_type").(string) + location := d.Get("location").(string) + tags := d.Get("tags").(map[string]interface{}) + + opts := storage.AccountCreateParameters{ + Location: &location, + Properties: &storage.AccountPropertiesCreateParameters{ + AccountType: storage.AccountType(accountType), + }, + Tags: expandTags(tags), + } + + _, err := client.Create(resourceGroupName, storageAccountName, opts, make(chan struct{})) + if err != nil { + return fmt.Errorf("Error creating Azure Storage Account '%s': %s", storageAccountName, err) + } + + // The only way to get the ID back apparently is to read the resource again + read, err := client.GetProperties(resourceGroupName, storageAccountName) + if err != nil { + return err + } + if read.ID == nil { + return fmt.Errorf("Cannot read Storage Account %s (resource group %s) ID", + storageAccountName, resourceGroupName) + } + + d.SetId(*read.ID) + + return resourceArmStorageAccountRead(d, meta) +} + +// resourceArmStorageAccountUpdate is unusual in the ARM API where most resources have a combined +// and idempotent operation for CreateOrUpdate. In particular updating all of the parameters +// available requires a call to Update per parameter... +func resourceArmStorageAccountUpdate(d *schema.ResourceData, meta interface{}) error { + client := meta.(*ArmClient).storageServiceClient + id, err := parseAzureResourceID(d.Id()) + if err != nil { + return err + } + storageAccountName := id.Path["storageAccounts"] + resourceGroupName := id.ResourceGroup + + d.Partial(true) + + if d.HasChange("account_type") { + accountType := d.Get("account_type").(string) + + opts := storage.AccountUpdateParameters{ + Properties: &storage.AccountPropertiesUpdateParameters{ + AccountType: storage.AccountType(accountType), + }, + } + _, err := client.Update(resourceGroupName, storageAccountName, opts) + if err != nil { + return fmt.Errorf("Error updating Azure Storage Account type %q: %s", storageAccountName, err) + } + + d.SetPartial("account_type") + } + + if d.HasChange("tags") { + tags := d.Get("tags").(map[string]interface{}) + + opts := storage.AccountUpdateParameters{ + Tags: expandTags(tags), + } + _, err := client.Update(resourceGroupName, storageAccountName, opts) + if err != nil { + return fmt.Errorf("Error updating Azure Storage Account tags %q: %s", storageAccountName, err) + } + + d.SetPartial("tags") + } + + d.Partial(false) + return nil +} + +func resourceArmStorageAccountRead(d *schema.ResourceData, meta interface{}) error { + client := meta.(*ArmClient).storageServiceClient + + id, err := parseAzureResourceID(d.Id()) + if err != nil { + return err + } + name := id.Path["storageAccounts"] + resGroup := id.ResourceGroup + + resp, err := client.GetProperties(resGroup, name) + if err != nil { + if resp.StatusCode == http.StatusNotFound { + d.SetId("") + return nil + } + + return fmt.Errorf("Error reading the state of AzureRM Storage Account %q: %s", name, err) + } + + keys, err := client.ListKeys(resGroup, name) + if err != nil { + return err + } + + d.Set("primary_access_key", keys.Key1) + d.Set("secondary_access_key", keys.Key2) + d.Set("location", resp.Location) + d.Set("account_type", resp.Properties.AccountType) + d.Set("primary_location", resp.Properties.PrimaryLocation) + d.Set("secondary_location", resp.Properties.SecondaryLocation) + + if resp.Properties.PrimaryEndpoints != nil { + d.Set("primary_blob_endpoint", resp.Properties.PrimaryEndpoints.Blob) + d.Set("primary_queue_endpoint", resp.Properties.PrimaryEndpoints.Queue) + d.Set("primary_table_endpoint", resp.Properties.PrimaryEndpoints.Table) + d.Set("primary_file_endpoint", resp.Properties.PrimaryEndpoints.File) + } + + if resp.Properties.SecondaryEndpoints != nil { + if resp.Properties.SecondaryEndpoints.Blob != nil { + d.Set("secondary_blob_endpoint", resp.Properties.SecondaryEndpoints.Blob) + } else { + d.Set("secondary_blob_endpoint", "") + } + if resp.Properties.SecondaryEndpoints.Queue != nil { + d.Set("secondary_queue_endpoint", resp.Properties.SecondaryEndpoints.Queue) + } else { + d.Set("secondary_queue_endpoint", "") + } + if resp.Properties.SecondaryEndpoints.Table != nil { + d.Set("secondary_table_endpoint", resp.Properties.SecondaryEndpoints.Table) + } else { + d.Set("secondary_table_endpoint", "") + } + } + + flattenAndSetTags(d, resp.Tags) + + return nil +} + +func resourceArmStorageAccountDelete(d *schema.ResourceData, meta interface{}) error { + client := meta.(*ArmClient).storageServiceClient + + id, err := parseAzureResourceID(d.Id()) + if err != nil { + return err + } + name := id.Path["storageAccounts"] + resGroup := id.ResourceGroup + + _, err = client.Delete(resGroup, name) + if err != nil { + return fmt.Errorf("Error issuing AzureRM delete request for storage account %q: %s", name, err) + } + + return nil +} + +func validateArmStorageAccountName(v interface{}, k string) (ws []string, es []error) { + input := v.(string) + + if !regexp.MustCompile(`\A([a-z0-9]{3,24})\z`).MatchString(input) { + es = append(es, fmt.Errorf("name can only consist of lowercase letters and numbers, and must be between 3 and 24 characters long")) + } + + return +} + +func validateArmStorageAccountType(v interface{}, k string) (ws []string, es []error) { + validAccountTypes := []string{"standard_lrs", "standard_zrs", + "standard_grs", "standard_ragrs", "premium_lrs"} + + input := strings.ToLower(v.(string)) + + for _, valid := range validAccountTypes { + if valid == input { + return + } + } + + es = append(es, fmt.Errorf("Invalid storage account type %q", input)) + return +} diff --git a/builtin/providers/azurerm/resource_arm_storage_account_test.go b/builtin/providers/azurerm/resource_arm_storage_account_test.go index 9bcc694f2..6cad5a1f5 100644 --- a/builtin/providers/azurerm/resource_arm_storage_account_test.go +++ b/builtin/providers/azurerm/resource_arm_storage_account_test.go @@ -1,166 +1,166 @@ package azurerm -//import ( -// "fmt" -// "net/http" -// "testing" -// -// "github.com/hashicorp/terraform/helper/resource" -// "github.com/hashicorp/terraform/terraform" -//) -// -//func TestValidateArmStorageAccountType(t *testing.T) { -// testCases := []struct { -// input string -// shouldError bool -// }{ -// {"standard_lrs", false}, -// {"invalid", true}, -// } -// -// for _, test := range testCases { -// _, es := validateArmStorageAccountType(test.input, "account_type") -// -// if test.shouldError && len(es) == 0 { -// t.Fatalf("Expected validating account_type %q to fail", test.input) -// } -// } -//} -// -//func TestValidateArmStorageAccountName(t *testing.T) { -// testCases := []struct { -// input string -// shouldError bool -// }{ -// {"ab", true}, -// {"ABC", true}, -// {"abc", false}, -// {"123456789012345678901234", false}, -// {"1234567890123456789012345", true}, -// {"abc12345", false}, -// } -// -// for _, test := range testCases { -// _, es := validateArmStorageAccountName(test.input, "name") -// -// if test.shouldError && len(es) == 0 { -// t.Fatalf("Expected validating name %q to fail", test.input) -// } -// } -//} -// -//func TestAccAzureRMStorageAccount_basic(t *testing.T) { -// resource.Test(t, resource.TestCase{ -// PreCheck: func() { testAccPreCheck(t) }, -// Providers: testAccProviders, -// CheckDestroy: testCheckAzureRMStorageAccountDestroy, -// Steps: []resource.TestStep{ -// resource.TestStep{ -// Config: testAccAzureRMStorageAccount_basic, -// Check: resource.ComposeTestCheckFunc( -// testCheckAzureRMStorageAccountExists("azurerm_storage_account.testsa"), -// resource.TestCheckResourceAttr("azurerm_storage_account.testsa", "account_type", "Standard_LRS"), -// resource.TestCheckResourceAttr("azurerm_storage_account.testsa", "tags.#", "1"), -// resource.TestCheckResourceAttr("azurerm_storage_account.testsa", "tags.environment", "production"), -// ), -// }, -// -// resource.TestStep{ -// Config: testAccAzureRMStorageAccount_update, -// Check: resource.ComposeTestCheckFunc( -// testCheckAzureRMStorageAccountExists("azurerm_storage_account.testsa"), -// resource.TestCheckResourceAttr("azurerm_storage_account.testsa", "account_type", "Standard_GRS"), -// resource.TestCheckResourceAttr("azurerm_storage_account.testsa", "tags.#", "1"), -// resource.TestCheckResourceAttr("azurerm_storage_account.testsa", "tags.environment", "staging"), -// ), -// }, -// }, -// }) -//} -// -//func testCheckAzureRMStorageAccountExists(name string) resource.TestCheckFunc { -// return func(s *terraform.State) error { -// // Ensure we have enough information in state to look up in API -// rs, ok := s.RootModule().Resources[name] -// if !ok { -// return fmt.Errorf("Not found: %s", name) -// } -// -// storageAccount := rs.Primary.Attributes["name"] -// resourceGroup := rs.Primary.Attributes["resource_group_name"] -// -// // Ensure resource group exists in API -// conn := testAccProvider.Meta().(*ArmClient).storageServiceClient -// -// resp, err := conn.GetProperties(resourceGroup, storageAccount) -// if err != nil { -// return fmt.Errorf("Bad: Get on storageServiceClient: %s", err) -// } -// -// if resp.StatusCode == http.StatusNotFound { -// return fmt.Errorf("Bad: StorageAccount %q (resource group: %q) does not exist", name, resourceGroup) -// } -// -// return nil -// } -//} -// -//func testCheckAzureRMStorageAccountDestroy(s *terraform.State) error { -// conn := testAccProvider.Meta().(*ArmClient).storageServiceClient -// -// for _, rs := range s.RootModule().Resources { -// if rs.Type != "azurerm_storage_account" { -// continue -// } -// -// name := rs.Primary.Attributes["name"] -// resourceGroup := rs.Primary.Attributes["resource_group_name"] -// -// resp, err := conn.GetProperties(resourceGroup, name) -// if err != nil { -// return nil -// } -// -// if resp.StatusCode != http.StatusNotFound { -// return fmt.Errorf("Storage Account still exists:\n%#v", resp.Properties) -// } -// } -// -// return nil -//} -// -//var testAccAzureRMStorageAccount_basic = ` -//resource "azurerm_resource_group" "testrg" { -// name = "testAccAzureRMStorageAccountBasic" -// location = "westus" -//} -// -//resource "azurerm_storage_account" "testsa" { -// name = "unlikely23exst2acct1435" -// resource_group_name = "${azurerm_resource_group.testrg.name}" -// -// location = "westus" -// account_type = "Standard_LRS" -// -// tags { -// environment = "production" -// } -//}` -// -//var testAccAzureRMStorageAccount_update = ` -//resource "azurerm_resource_group" "testrg" { -// name = "testAccAzureRMStorageAccountBasic" -// location = "westus" -//} -// -//resource "azurerm_storage_account" "testsa" { -// name = "unlikely23exst2acct1435" -// resource_group_name = "${azurerm_resource_group.testrg.name}" -// -// location = "westus" -// account_type = "Standard_GRS" -// -// tags { -// environment = "staging" -// } -//}` +import ( + "fmt" + "net/http" + "testing" + + "github.com/hashicorp/terraform/helper/resource" + "github.com/hashicorp/terraform/terraform" +) + +func TestValidateArmStorageAccountType(t *testing.T) { + testCases := []struct { + input string + shouldError bool + }{ + {"standard_lrs", false}, + {"invalid", true}, + } + + for _, test := range testCases { + _, es := validateArmStorageAccountType(test.input, "account_type") + + if test.shouldError && len(es) == 0 { + t.Fatalf("Expected validating account_type %q to fail", test.input) + } + } +} + +func TestValidateArmStorageAccountName(t *testing.T) { + testCases := []struct { + input string + shouldError bool + }{ + {"ab", true}, + {"ABC", true}, + {"abc", false}, + {"123456789012345678901234", false}, + {"1234567890123456789012345", true}, + {"abc12345", false}, + } + + for _, test := range testCases { + _, es := validateArmStorageAccountName(test.input, "name") + + if test.shouldError && len(es) == 0 { + t.Fatalf("Expected validating name %q to fail", test.input) + } + } +} + +func TestAccAzureRMStorageAccount_basic(t *testing.T) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMStorageAccountDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccAzureRMStorageAccount_basic, + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMStorageAccountExists("azurerm_storage_account.testsa"), + resource.TestCheckResourceAttr("azurerm_storage_account.testsa", "account_type", "Standard_LRS"), + resource.TestCheckResourceAttr("azurerm_storage_account.testsa", "tags.#", "1"), + resource.TestCheckResourceAttr("azurerm_storage_account.testsa", "tags.environment", "production"), + ), + }, + + resource.TestStep{ + Config: testAccAzureRMStorageAccount_update, + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMStorageAccountExists("azurerm_storage_account.testsa"), + resource.TestCheckResourceAttr("azurerm_storage_account.testsa", "account_type", "Standard_GRS"), + resource.TestCheckResourceAttr("azurerm_storage_account.testsa", "tags.#", "1"), + resource.TestCheckResourceAttr("azurerm_storage_account.testsa", "tags.environment", "staging"), + ), + }, + }, + }) +} + +func testCheckAzureRMStorageAccountExists(name string) resource.TestCheckFunc { + return func(s *terraform.State) error { + // Ensure we have enough information in state to look up in API + rs, ok := s.RootModule().Resources[name] + if !ok { + return fmt.Errorf("Not found: %s", name) + } + + storageAccount := rs.Primary.Attributes["name"] + resourceGroup := rs.Primary.Attributes["resource_group_name"] + + // Ensure resource group exists in API + conn := testAccProvider.Meta().(*ArmClient).storageServiceClient + + resp, err := conn.GetProperties(resourceGroup, storageAccount) + if err != nil { + return fmt.Errorf("Bad: Get on storageServiceClient: %s", err) + } + + if resp.StatusCode == http.StatusNotFound { + return fmt.Errorf("Bad: StorageAccount %q (resource group: %q) does not exist", name, resourceGroup) + } + + return nil + } +} + +func testCheckAzureRMStorageAccountDestroy(s *terraform.State) error { + conn := testAccProvider.Meta().(*ArmClient).storageServiceClient + + for _, rs := range s.RootModule().Resources { + if rs.Type != "azurerm_storage_account" { + continue + } + + name := rs.Primary.Attributes["name"] + resourceGroup := rs.Primary.Attributes["resource_group_name"] + + resp, err := conn.GetProperties(resourceGroup, name) + if err != nil { + return nil + } + + if resp.StatusCode != http.StatusNotFound { + return fmt.Errorf("Storage Account still exists:\n%#v", resp.Properties) + } + } + + return nil +} + +var testAccAzureRMStorageAccount_basic = ` +resource "azurerm_resource_group" "testrg" { + name = "testAccAzureRMStorageAccountBasic" + location = "westus" +} + +resource "azurerm_storage_account" "testsa" { + name = "unlikely23exst2acct1435" + resource_group_name = "${azurerm_resource_group.testrg.name}" + + location = "westus" + account_type = "Standard_LRS" + + tags { + environment = "production" + } +}` + +var testAccAzureRMStorageAccount_update = ` +resource "azurerm_resource_group" "testrg" { + name = "testAccAzureRMStorageAccountBasic" + location = "westus" +} + +resource "azurerm_storage_account" "testsa" { + name = "unlikely23exst2acct1435" + resource_group_name = "${azurerm_resource_group.testrg.name}" + + location = "westus" + account_type = "Standard_GRS" + + tags { + environment = "staging" + } +}`