diff --git a/builtin/providers/azurerm/provider.go b/builtin/providers/azurerm/provider.go index de93f31f3..612b91731 100644 --- a/builtin/providers/azurerm/provider.go +++ b/builtin/providers/azurerm/provider.go @@ -55,11 +55,11 @@ 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_container": resourceArmStorageContainer(), - "azurerm_storage_queue": resourceArmStorageQueue(), - "azurerm_subnet": resourceArmSubnet(), + "azurerm_storage_account": resourceArmStorageAccount(), + "azurerm_storage_blob": resourceArmStorageBlob(), + "azurerm_storage_container": resourceArmStorageContainer(), + "azurerm_storage_queue": resourceArmStorageQueue(), + "azurerm_subnet": resourceArmSubnet(), //"azurerm_template_deployment": resourceArmTemplateDeployment(), //"azurerm_virtual_machine": resourceArmVirtualMachine(), "azurerm_virtual_network": resourceArmVirtualNetwork(), diff --git a/builtin/providers/azurerm/resource_arm_storage_container.go b/builtin/providers/azurerm/resource_arm_storage_container.go index 1b3c3bd9b..afdcd263c 100644 --- a/builtin/providers/azurerm/resource_arm_storage_container.go +++ b/builtin/providers/azurerm/resource_arm_storage_container.go @@ -1,227 +1,227 @@ package azurerm -//import ( -// "fmt" -// "log" -// "strings" -// -// "regexp" -// -// "github.com/Azure/azure-sdk-for-go/storage" -// "github.com/hashicorp/terraform/helper/schema" -//) -// -//func resourceArmStorageContainer() *schema.Resource { -// return &schema.Resource{ -// Create: resourceArmStorageContainerCreate, -// Read: resourceArmStorageContainerRead, -// Exists: resourceArmStorageContainerExists, -// Delete: resourceArmStorageContainerDelete, -// -// Schema: map[string]*schema.Schema{ -// "name": &schema.Schema{ -// Type: schema.TypeString, -// Required: true, -// ForceNew: true, -// ValidateFunc: validateArmStorageContainerName, -// }, -// "resource_group_name": &schema.Schema{ -// Type: schema.TypeString, -// Required: true, -// ForceNew: true, -// }, -// "storage_account_name": &schema.Schema{ -// Type: schema.TypeString, -// Required: true, -// ForceNew: true, -// }, -// "container_access_type": &schema.Schema{ -// Type: schema.TypeString, -// Optional: true, -// ForceNew: true, -// Default: "private", -// ValidateFunc: validateArmStorageContainerAccessType, -// }, -// "properties": &schema.Schema{ -// Type: schema.TypeMap, -// Computed: true, -// }, -// }, -// } -//} -// -////Following the naming convention as laid out in the docs -//func validateArmStorageContainerName(v interface{}, k string) (ws []string, errors []error) { -// value := v.(string) -// if !regexp.MustCompile(`^[0-9a-z-]+$`).MatchString(value) { -// errors = append(errors, fmt.Errorf( -// "only lowercase alphanumeric characters and hyphens allowed in %q: %q", -// k, value)) -// } -// if len(value) < 3 || len(value) > 63 { -// errors = append(errors, fmt.Errorf( -// "%q must be between 3 and 63 characters: %q", k, value)) -// } -// if regexp.MustCompile(`^-`).MatchString(value) { -// errors = append(errors, fmt.Errorf( -// "%q cannot begin with a hyphen: %q", k, value)) -// } -// return -//} -// -//func validateArmStorageContainerAccessType(v interface{}, k string) (ws []string, errors []error) { -// value := strings.ToLower(v.(string)) -// validTypes := map[string]struct{}{ -// "private": struct{}{}, -// "blob": struct{}{}, -// "container": struct{}{}, -// } -// -// if _, ok := validTypes[value]; !ok { -// errors = append(errors, fmt.Errorf("Storage container access type %q is invalid, must be %q, %q or %q", value, "private", "blob", "page")) -// } -// return -//} -// -//func resourceArmStorageContainerCreate(d *schema.ResourceData, meta interface{}) error { -// armClient := meta.(*ArmClient) -// -// resourceGroupName := d.Get("resource_group_name").(string) -// storageAccountName := d.Get("storage_account_name").(string) -// -// blobClient, accountExists, err := armClient.getBlobStorageClientForStorageAccount(resourceGroupName, storageAccountName) -// if err != nil { -// return err -// } -// if !accountExists { -// return fmt.Errorf("Storage Account %q Not Found", storageAccountName) -// } -// -// name := d.Get("name").(string) -// -// var accessType storage.ContainerAccessType -// if d.Get("container_access_type").(string) == "private" { -// accessType = storage.ContainerAccessType("") -// } else { -// accessType = storage.ContainerAccessType(d.Get("container_access_type").(string)) -// } -// -// log.Printf("[INFO] Creating container %q in storage account %q.", name, storageAccountName) -// _, err = blobClient.CreateContainerIfNotExists(name, accessType) -// if err != nil { -// return fmt.Errorf("Error creating container %q in storage account %q: %s", name, storageAccountName, err) -// } -// -// d.SetId(name) -// return resourceArmStorageContainerRead(d, meta) -//} -// -//// resourceAzureStorageContainerRead does all the necessary API calls to -//// read the status of the storage container off Azure. -//func resourceArmStorageContainerRead(d *schema.ResourceData, meta interface{}) error { -// armClient := meta.(*ArmClient) -// -// resourceGroupName := d.Get("resource_group_name").(string) -// storageAccountName := d.Get("storage_account_name").(string) -// -// blobClient, accountExists, err := armClient.getBlobStorageClientForStorageAccount(resourceGroupName, storageAccountName) -// if err != nil { -// return err -// } -// if !accountExists { -// log.Printf("[DEBUG] Storage account %q not found, removing container %q from state", storageAccountName, d.Id()) -// d.SetId("") -// return nil -// } -// -// name := d.Get("name").(string) -// containers, err := blobClient.ListContainers(storage.ListContainersParameters{ -// Prefix: name, -// Timeout: 90, -// }) -// if err != nil { -// return fmt.Errorf("Failed to retrieve storage containers in account %q: %s", name, err) -// } -// -// var found bool -// for _, cont := range containers.Containers { -// if cont.Name == name { -// found = true -// -// props := make(map[string]interface{}) -// props["last_modified"] = cont.Properties.LastModified -// props["lease_status"] = cont.Properties.LeaseStatus -// props["lease_state"] = cont.Properties.LeaseState -// props["lease_duration"] = cont.Properties.LeaseDuration -// -// d.Set("properties", props) -// } -// } -// -// if !found { -// log.Printf("[INFO] Storage container %q does not exist in account %q, removing from state...", name, storageAccountName) -// d.SetId("") -// } -// -// return nil -//} -// -//func resourceArmStorageContainerExists(d *schema.ResourceData, meta interface{}) (bool, error) { -// armClient := meta.(*ArmClient) -// -// resourceGroupName := d.Get("resource_group_name").(string) -// storageAccountName := d.Get("storage_account_name").(string) -// -// blobClient, accountExists, err := armClient.getBlobStorageClientForStorageAccount(resourceGroupName, storageAccountName) -// if err != nil { -// return false, err -// } -// if !accountExists { -// log.Printf("[DEBUG] Storage account %q not found, removing container %q from state", storageAccountName, d.Id()) -// d.SetId("") -// return false, nil -// } -// -// name := d.Get("name").(string) -// -// log.Printf("[INFO] Checking existence of storage container %q in storage account %q", name, storageAccountName) -// exists, err := blobClient.ContainerExists(name) -// if err != nil { -// return false, fmt.Errorf("Error querying existence of storage container %q in storage account %q: %s", name, storageAccountName, err) -// } -// -// if !exists { -// log.Printf("[INFO] Storage container %q does not exist in account %q, removing from state...", name, storageAccountName) -// d.SetId("") -// } -// -// return exists, nil -//} -// -//// resourceAzureStorageContainerDelete does all the necessary API calls to -//// delete a storage container off Azure. -//func resourceArmStorageContainerDelete(d *schema.ResourceData, meta interface{}) error { -// armClient := meta.(*ArmClient) -// -// resourceGroupName := d.Get("resource_group_name").(string) -// storageAccountName := d.Get("storage_account_name").(string) -// -// blobClient, accountExists, err := armClient.getBlobStorageClientForStorageAccount(resourceGroupName, storageAccountName) -// if err != nil { -// return err -// } -// if !accountExists { -// log.Printf("[INFO]Storage Account %q doesn't exist so the container won't exist", storageAccountName) -// return nil -// } -// -// name := d.Get("name").(string) -// -// log.Printf("[INFO] Deleting storage container %q in account %q", name, storageAccountName) -// if _, err := blobClient.DeleteContainerIfExists(name); err != nil { -// return fmt.Errorf("Error deleting storage container %q from storage account %q: %s", name, storageAccountName, err) -// } -// -// d.SetId("") -// return nil -//} +import ( + "fmt" + "log" + "strings" + + "regexp" + + "github.com/Azure/azure-sdk-for-go/storage" + "github.com/hashicorp/terraform/helper/schema" +) + +func resourceArmStorageContainer() *schema.Resource { + return &schema.Resource{ + Create: resourceArmStorageContainerCreate, + Read: resourceArmStorageContainerRead, + Exists: resourceArmStorageContainerExists, + Delete: resourceArmStorageContainerDelete, + + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validateArmStorageContainerName, + }, + "resource_group_name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + "storage_account_name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + "container_access_type": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Default: "private", + ValidateFunc: validateArmStorageContainerAccessType, + }, + "properties": { + Type: schema.TypeMap, + Computed: true, + }, + }, + } +} + +//Following the naming convention as laid out in the docs +func validateArmStorageContainerName(v interface{}, k string) (ws []string, errors []error) { + value := v.(string) + if !regexp.MustCompile(`^[0-9a-z-]+$`).MatchString(value) { + errors = append(errors, fmt.Errorf( + "only lowercase alphanumeric characters and hyphens allowed in %q: %q", + k, value)) + } + if len(value) < 3 || len(value) > 63 { + errors = append(errors, fmt.Errorf( + "%q must be between 3 and 63 characters: %q", k, value)) + } + if regexp.MustCompile(`^-`).MatchString(value) { + errors = append(errors, fmt.Errorf( + "%q cannot begin with a hyphen: %q", k, value)) + } + return +} + +func validateArmStorageContainerAccessType(v interface{}, k string) (ws []string, errors []error) { + value := strings.ToLower(v.(string)) + validTypes := map[string]struct{}{ + "private": struct{}{}, + "blob": struct{}{}, + "container": struct{}{}, + } + + if _, ok := validTypes[value]; !ok { + errors = append(errors, fmt.Errorf("Storage container access type %q is invalid, must be %q, %q or %q", value, "private", "blob", "page")) + } + return +} + +func resourceArmStorageContainerCreate(d *schema.ResourceData, meta interface{}) error { + armClient := meta.(*ArmClient) + + resourceGroupName := d.Get("resource_group_name").(string) + storageAccountName := d.Get("storage_account_name").(string) + + blobClient, accountExists, err := armClient.getBlobStorageClientForStorageAccount(resourceGroupName, storageAccountName) + if err != nil { + return err + } + if !accountExists { + return fmt.Errorf("Storage Account %q Not Found", storageAccountName) + } + + name := d.Get("name").(string) + + var accessType storage.ContainerAccessType + if d.Get("container_access_type").(string) == "private" { + accessType = storage.ContainerAccessType("") + } else { + accessType = storage.ContainerAccessType(d.Get("container_access_type").(string)) + } + + log.Printf("[INFO] Creating container %q in storage account %q.", name, storageAccountName) + _, err = blobClient.CreateContainerIfNotExists(name, accessType) + if err != nil { + return fmt.Errorf("Error creating container %q in storage account %q: %s", name, storageAccountName, err) + } + + d.SetId(name) + return resourceArmStorageContainerRead(d, meta) +} + +// resourceAzureStorageContainerRead does all the necessary API calls to +// read the status of the storage container off Azure. +func resourceArmStorageContainerRead(d *schema.ResourceData, meta interface{}) error { + armClient := meta.(*ArmClient) + + resourceGroupName := d.Get("resource_group_name").(string) + storageAccountName := d.Get("storage_account_name").(string) + + blobClient, accountExists, err := armClient.getBlobStorageClientForStorageAccount(resourceGroupName, storageAccountName) + if err != nil { + return err + } + if !accountExists { + log.Printf("[DEBUG] Storage account %q not found, removing container %q from state", storageAccountName, d.Id()) + d.SetId("") + return nil + } + + name := d.Get("name").(string) + containers, err := blobClient.ListContainers(storage.ListContainersParameters{ + Prefix: name, + Timeout: 90, + }) + if err != nil { + return fmt.Errorf("Failed to retrieve storage containers in account %q: %s", name, err) + } + + var found bool + for _, cont := range containers.Containers { + if cont.Name == name { + found = true + + props := make(map[string]interface{}) + props["last_modified"] = cont.Properties.LastModified + props["lease_status"] = cont.Properties.LeaseStatus + props["lease_state"] = cont.Properties.LeaseState + props["lease_duration"] = cont.Properties.LeaseDuration + + d.Set("properties", props) + } + } + + if !found { + log.Printf("[INFO] Storage container %q does not exist in account %q, removing from state...", name, storageAccountName) + d.SetId("") + } + + return nil +} + +func resourceArmStorageContainerExists(d *schema.ResourceData, meta interface{}) (bool, error) { + armClient := meta.(*ArmClient) + + resourceGroupName := d.Get("resource_group_name").(string) + storageAccountName := d.Get("storage_account_name").(string) + + blobClient, accountExists, err := armClient.getBlobStorageClientForStorageAccount(resourceGroupName, storageAccountName) + if err != nil { + return false, err + } + if !accountExists { + log.Printf("[DEBUG] Storage account %q not found, removing container %q from state", storageAccountName, d.Id()) + d.SetId("") + return false, nil + } + + name := d.Get("name").(string) + + log.Printf("[INFO] Checking existence of storage container %q in storage account %q", name, storageAccountName) + exists, err := blobClient.ContainerExists(name) + if err != nil { + return false, fmt.Errorf("Error querying existence of storage container %q in storage account %q: %s", name, storageAccountName, err) + } + + if !exists { + log.Printf("[INFO] Storage container %q does not exist in account %q, removing from state...", name, storageAccountName) + d.SetId("") + } + + return exists, nil +} + +// resourceAzureStorageContainerDelete does all the necessary API calls to +// delete a storage container off Azure. +func resourceArmStorageContainerDelete(d *schema.ResourceData, meta interface{}) error { + armClient := meta.(*ArmClient) + + resourceGroupName := d.Get("resource_group_name").(string) + storageAccountName := d.Get("storage_account_name").(string) + + blobClient, accountExists, err := armClient.getBlobStorageClientForStorageAccount(resourceGroupName, storageAccountName) + if err != nil { + return err + } + if !accountExists { + log.Printf("[INFO]Storage Account %q doesn't exist so the container won't exist", storageAccountName) + return nil + } + + name := d.Get("name").(string) + + log.Printf("[INFO] Deleting storage container %q in account %q", name, storageAccountName) + if _, err := blobClient.DeleteContainerIfExists(name); err != nil { + return fmt.Errorf("Error deleting storage container %q from storage account %q: %s", name, storageAccountName, err) + } + + d.SetId("") + return nil +} diff --git a/builtin/providers/azurerm/resource_arm_storage_container_test.go b/builtin/providers/azurerm/resource_arm_storage_container_test.go index 17e29a258..ee92b14bd 100644 --- a/builtin/providers/azurerm/resource_arm_storage_container_test.go +++ b/builtin/providers/azurerm/resource_arm_storage_container_test.go @@ -1,241 +1,241 @@ package azurerm -//import ( -// "fmt" -// "log" -// "strings" -// "testing" -// -// "github.com/Azure/azure-sdk-for-go/storage" -// "github.com/hashicorp/terraform/helper/acctest" -// "github.com/hashicorp/terraform/helper/resource" -// "github.com/hashicorp/terraform/terraform" -//) -// -//func TestAccAzureRMStorageContainer_basic(t *testing.T) { -// var c storage.Container -// -// ri := acctest.RandInt() -// rs := strings.ToLower(acctest.RandString(11)) -// config := fmt.Sprintf(testAccAzureRMStorageContainer_basic, ri, rs) -// -// resource.Test(t, resource.TestCase{ -// PreCheck: func() { testAccPreCheck(t) }, -// Providers: testAccProviders, -// CheckDestroy: testCheckAzureRMStorageContainerDestroy, -// Steps: []resource.TestStep{ -// resource.TestStep{ -// Config: config, -// Check: resource.ComposeTestCheckFunc( -// testCheckAzureRMStorageContainerExists("azurerm_storage_container.test", &c), -// ), -// }, -// }, -// }) -//} -// -//func TestAccAzureRMStorageContainer_disappears(t *testing.T) { -// var c storage.Container -// -// ri := acctest.RandInt() -// rs := strings.ToLower(acctest.RandString(11)) -// config := fmt.Sprintf(testAccAzureRMStorageContainer_basic, ri, rs) -// -// resource.Test(t, resource.TestCase{ -// PreCheck: func() { testAccPreCheck(t) }, -// Providers: testAccProviders, -// CheckDestroy: testCheckAzureRMStorageContainerDestroy, -// Steps: []resource.TestStep{ -// resource.TestStep{ -// Config: config, -// Check: resource.ComposeTestCheckFunc( -// testCheckAzureRMStorageContainerExists("azurerm_storage_container.test", &c), -// testAccARMStorageContainerDisappears("azurerm_storage_container.test", &c), -// ), -// ExpectNonEmptyPlan: true, -// }, -// }, -// }) -//} -// -//func testCheckAzureRMStorageContainerExists(name string, c *storage.Container) resource.TestCheckFunc { -// return func(s *terraform.State) error { -// -// rs, ok := s.RootModule().Resources[name] -// if !ok { -// return fmt.Errorf("Not found: %s", name) -// } -// -// name := rs.Primary.Attributes["name"] -// storageAccountName := rs.Primary.Attributes["storage_account_name"] -// resourceGroup, hasResourceGroup := rs.Primary.Attributes["resource_group_name"] -// if !hasResourceGroup { -// return fmt.Errorf("Bad: no resource group found in state for storage container: %s", name) -// } -// -// armClient := testAccProvider.Meta().(*ArmClient) -// blobClient, accountExists, err := armClient.getBlobStorageClientForStorageAccount(resourceGroup, storageAccountName) -// if err != nil { -// return err -// } -// if !accountExists { -// return fmt.Errorf("Bad: Storage Account %q does not exist", storageAccountName) -// } -// -// containers, err := blobClient.ListContainers(storage.ListContainersParameters{ -// Prefix: name, -// Timeout: 90, -// }) -// -// if len(containers.Containers) == 0 { -// return fmt.Errorf("Bad: Storage Container %q (storage account: %q) does not exist", name, storageAccountName) -// } -// -// var found bool -// for _, container := range containers.Containers { -// if container.Name == name { -// found = true -// *c = container -// } -// } -// -// if !found { -// return fmt.Errorf("Bad: Storage Container %q (storage account: %q) does not exist", name, storageAccountName) -// } -// -// return nil -// } -//} -// -//func testAccARMStorageContainerDisappears(name string, c *storage.Container) resource.TestCheckFunc { -// return func(s *terraform.State) error { -// rs, ok := s.RootModule().Resources[name] -// if !ok { -// return fmt.Errorf("Not found: %s", name) -// } -// -// armClient := testAccProvider.Meta().(*ArmClient) -// -// storageAccountName := rs.Primary.Attributes["storage_account_name"] -// resourceGroup, hasResourceGroup := rs.Primary.Attributes["resource_group_name"] -// if !hasResourceGroup { -// return fmt.Errorf("Bad: no resource group found in state for storage container: %s", c.Name) -// } -// -// blobClient, accountExists, err := armClient.getBlobStorageClientForStorageAccount(resourceGroup, storageAccountName) -// if err != nil { -// return err -// } -// if !accountExists { -// log.Printf("[INFO]Storage Account %q doesn't exist so the container won't exist", storageAccountName) -// return nil -// } -// -// _, err = blobClient.DeleteContainerIfExists(c.Name) -// if err != nil { -// return err -// } -// -// return nil -// } -//} -// -//func testCheckAzureRMStorageContainerDestroy(s *terraform.State) error { -// for _, rs := range s.RootModule().Resources { -// if rs.Type != "azurerm_storage_container" { -// continue -// } -// -// name := rs.Primary.Attributes["name"] -// storageAccountName := rs.Primary.Attributes["storage_account_name"] -// resourceGroup, hasResourceGroup := rs.Primary.Attributes["resource_group_name"] -// if !hasResourceGroup { -// return fmt.Errorf("Bad: no resource group found in state for storage container: %s", name) -// } -// -// armClient := testAccProvider.Meta().(*ArmClient) -// blobClient, accountExists, err := armClient.getBlobStorageClientForStorageAccount(resourceGroup, storageAccountName) -// if err != nil { -// //If we can't get keys then the blob can't exist -// return nil -// } -// if !accountExists { -// return nil -// } -// -// containers, err := blobClient.ListContainers(storage.ListContainersParameters{ -// Prefix: name, -// Timeout: 90, -// }) -// -// if err != nil { -// return nil -// } -// -// var found bool -// for _, container := range containers.Containers { -// if container.Name == name { -// found = true -// } -// } -// -// if found { -// return fmt.Errorf("Bad: Storage Container %q (storage account: %q) still exist", name, storageAccountName) -// } -// } -// -// return nil -//} -// -//func TestValidateArmStorageContainerName(t *testing.T) { -// validNames := []string{ -// "valid-name", -// "valid02-name", -// } -// for _, v := range validNames { -// _, errors := validateArmStorageContainerName(v, "name") -// if len(errors) != 0 { -// t.Fatalf("%q should be a valid Storage Container Name: %q", v, errors) -// } -// } -// -// invalidNames := []string{ -// "InvalidName1", -// "-invalidname1", -// "invalid_name", -// "invalid!", -// "ww", -// strings.Repeat("w", 65), -// } -// for _, v := range invalidNames { -// _, errors := validateArmStorageContainerName(v, "name") -// if len(errors) == 0 { -// t.Fatalf("%q should be an invalid Storage Container Name", v) -// } -// } -//} -// -//var testAccAzureRMStorageContainer_basic = ` -//resource "azurerm_resource_group" "test" { -// name = "acctestrg-%d" -// location = "westus" -//} -// -//resource "azurerm_storage_account" "test" { -// name = "acctestacc%s" -// resource_group_name = "${azurerm_resource_group.test.name}" -// location = "westus" -// account_type = "Standard_LRS" -// -// tags { -// environment = "staging" -// } -//} -// -//resource "azurerm_storage_container" "test" { -// name = "vhds" -// resource_group_name = "${azurerm_resource_group.test.name}" -// storage_account_name = "${azurerm_storage_account.test.name}" -// container_access_type = "private" -//} -//` +import ( + "fmt" + "log" + "strings" + "testing" + + "github.com/Azure/azure-sdk-for-go/storage" + "github.com/hashicorp/terraform/helper/acctest" + "github.com/hashicorp/terraform/helper/resource" + "github.com/hashicorp/terraform/terraform" +) + +func TestAccAzureRMStorageContainer_basic(t *testing.T) { + var c storage.Container + + ri := acctest.RandInt() + rs := strings.ToLower(acctest.RandString(11)) + config := fmt.Sprintf(testAccAzureRMStorageContainer_basic, ri, rs) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMStorageContainerDestroy, + Steps: []resource.TestStep{ + { + Config: config, + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMStorageContainerExists("azurerm_storage_container.test", &c), + ), + }, + }, + }) +} + +func TestAccAzureRMStorageContainer_disappears(t *testing.T) { + var c storage.Container + + ri := acctest.RandInt() + rs := strings.ToLower(acctest.RandString(11)) + config := fmt.Sprintf(testAccAzureRMStorageContainer_basic, ri, rs) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMStorageContainerDestroy, + Steps: []resource.TestStep{ + { + Config: config, + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMStorageContainerExists("azurerm_storage_container.test", &c), + testAccARMStorageContainerDisappears("azurerm_storage_container.test", &c), + ), + ExpectNonEmptyPlan: true, + }, + }, + }) +} + +func testCheckAzureRMStorageContainerExists(name string, c *storage.Container) resource.TestCheckFunc { + return func(s *terraform.State) error { + + rs, ok := s.RootModule().Resources[name] + if !ok { + return fmt.Errorf("Not found: %s", name) + } + + name := rs.Primary.Attributes["name"] + storageAccountName := rs.Primary.Attributes["storage_account_name"] + resourceGroup, hasResourceGroup := rs.Primary.Attributes["resource_group_name"] + if !hasResourceGroup { + return fmt.Errorf("Bad: no resource group found in state for storage container: %s", name) + } + + armClient := testAccProvider.Meta().(*ArmClient) + blobClient, accountExists, err := armClient.getBlobStorageClientForStorageAccount(resourceGroup, storageAccountName) + if err != nil { + return err + } + if !accountExists { + return fmt.Errorf("Bad: Storage Account %q does not exist", storageAccountName) + } + + containers, err := blobClient.ListContainers(storage.ListContainersParameters{ + Prefix: name, + Timeout: 90, + }) + + if len(containers.Containers) == 0 { + return fmt.Errorf("Bad: Storage Container %q (storage account: %q) does not exist", name, storageAccountName) + } + + var found bool + for _, container := range containers.Containers { + if container.Name == name { + found = true + *c = container + } + } + + if !found { + return fmt.Errorf("Bad: Storage Container %q (storage account: %q) does not exist", name, storageAccountName) + } + + return nil + } +} + +func testAccARMStorageContainerDisappears(name string, c *storage.Container) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[name] + if !ok { + return fmt.Errorf("Not found: %s", name) + } + + armClient := testAccProvider.Meta().(*ArmClient) + + storageAccountName := rs.Primary.Attributes["storage_account_name"] + resourceGroup, hasResourceGroup := rs.Primary.Attributes["resource_group_name"] + if !hasResourceGroup { + return fmt.Errorf("Bad: no resource group found in state for storage container: %s", c.Name) + } + + blobClient, accountExists, err := armClient.getBlobStorageClientForStorageAccount(resourceGroup, storageAccountName) + if err != nil { + return err + } + if !accountExists { + log.Printf("[INFO]Storage Account %q doesn't exist so the container won't exist", storageAccountName) + return nil + } + + _, err = blobClient.DeleteContainerIfExists(c.Name) + if err != nil { + return err + } + + return nil + } +} + +func testCheckAzureRMStorageContainerDestroy(s *terraform.State) error { + for _, rs := range s.RootModule().Resources { + if rs.Type != "azurerm_storage_container" { + continue + } + + name := rs.Primary.Attributes["name"] + storageAccountName := rs.Primary.Attributes["storage_account_name"] + resourceGroup, hasResourceGroup := rs.Primary.Attributes["resource_group_name"] + if !hasResourceGroup { + return fmt.Errorf("Bad: no resource group found in state for storage container: %s", name) + } + + armClient := testAccProvider.Meta().(*ArmClient) + blobClient, accountExists, err := armClient.getBlobStorageClientForStorageAccount(resourceGroup, storageAccountName) + if err != nil { + //If we can't get keys then the blob can't exist + return nil + } + if !accountExists { + return nil + } + + containers, err := blobClient.ListContainers(storage.ListContainersParameters{ + Prefix: name, + Timeout: 90, + }) + + if err != nil { + return nil + } + + var found bool + for _, container := range containers.Containers { + if container.Name == name { + found = true + } + } + + if found { + return fmt.Errorf("Bad: Storage Container %q (storage account: %q) still exist", name, storageAccountName) + } + } + + return nil +} + +func TestValidateArmStorageContainerName(t *testing.T) { + validNames := []string{ + "valid-name", + "valid02-name", + } + for _, v := range validNames { + _, errors := validateArmStorageContainerName(v, "name") + if len(errors) != 0 { + t.Fatalf("%q should be a valid Storage Container Name: %q", v, errors) + } + } + + invalidNames := []string{ + "InvalidName1", + "-invalidname1", + "invalid_name", + "invalid!", + "ww", + strings.Repeat("w", 65), + } + for _, v := range invalidNames { + _, errors := validateArmStorageContainerName(v, "name") + if len(errors) == 0 { + t.Fatalf("%q should be an invalid Storage Container Name", v) + } + } +} + +var testAccAzureRMStorageContainer_basic = ` +resource "azurerm_resource_group" "test" { + name = "acctestrg-%d" + location = "westus" +} + +resource "azurerm_storage_account" "test" { + name = "acctestacc%s" + resource_group_name = "${azurerm_resource_group.test.name}" + location = "westus" + account_type = "Standard_LRS" + + tags { + environment = "staging" + } +} + +resource "azurerm_storage_container" "test" { + name = "vhds" + resource_group_name = "${azurerm_resource_group.test.name}" + storage_account_name = "${azurerm_storage_account.test.name}" + container_access_type = "private" +} +`