github.com/danp/terraform@v0.9.5-0.20170426144147-39d740081351/builtin/providers/azurerm/resource_arm_storage_container.go (about)

     1  package azurerm
     2  
     3  import (
     4  	"fmt"
     5  	"log"
     6  	"strings"
     7  
     8  	"regexp"
     9  
    10  	"github.com/Azure/azure-sdk-for-go/storage"
    11  	"github.com/hashicorp/terraform/helper/schema"
    12  )
    13  
    14  func resourceArmStorageContainer() *schema.Resource {
    15  	return &schema.Resource{
    16  		Create: resourceArmStorageContainerCreate,
    17  		Read:   resourceArmStorageContainerRead,
    18  		Exists: resourceArmStorageContainerExists,
    19  		Delete: resourceArmStorageContainerDelete,
    20  
    21  		Schema: map[string]*schema.Schema{
    22  			"name": {
    23  				Type:         schema.TypeString,
    24  				Required:     true,
    25  				ForceNew:     true,
    26  				ValidateFunc: validateArmStorageContainerName,
    27  			},
    28  			"resource_group_name": {
    29  				Type:     schema.TypeString,
    30  				Required: true,
    31  				ForceNew: true,
    32  			},
    33  			"storage_account_name": {
    34  				Type:     schema.TypeString,
    35  				Required: true,
    36  				ForceNew: true,
    37  			},
    38  			"container_access_type": {
    39  				Type:         schema.TypeString,
    40  				Optional:     true,
    41  				ForceNew:     true,
    42  				Default:      "private",
    43  				ValidateFunc: validateArmStorageContainerAccessType,
    44  			},
    45  			"properties": {
    46  				Type:     schema.TypeMap,
    47  				Computed: true,
    48  			},
    49  		},
    50  	}
    51  }
    52  
    53  //Following the naming convention as laid out in the docs
    54  func validateArmStorageContainerName(v interface{}, k string) (ws []string, errors []error) {
    55  	value := v.(string)
    56  	if !regexp.MustCompile(`^\$root$|^[0-9a-z-]+$`).MatchString(value) {
    57  		errors = append(errors, fmt.Errorf(
    58  			"only lowercase alphanumeric characters and hyphens allowed in %q: %q",
    59  			k, value))
    60  	}
    61  	if len(value) < 3 || len(value) > 63 {
    62  		errors = append(errors, fmt.Errorf(
    63  			"%q must be between 3 and 63 characters: %q", k, value))
    64  	}
    65  	if regexp.MustCompile(`^-`).MatchString(value) {
    66  		errors = append(errors, fmt.Errorf(
    67  			"%q cannot begin with a hyphen: %q", k, value))
    68  	}
    69  	return
    70  }
    71  
    72  func validateArmStorageContainerAccessType(v interface{}, k string) (ws []string, errors []error) {
    73  	value := strings.ToLower(v.(string))
    74  	validTypes := map[string]struct{}{
    75  		"private":   struct{}{},
    76  		"blob":      struct{}{},
    77  		"container": struct{}{},
    78  	}
    79  
    80  	if _, ok := validTypes[value]; !ok {
    81  		errors = append(errors, fmt.Errorf("Storage container access type %q is invalid, must be %q, %q or %q", value, "private", "blob", "page"))
    82  	}
    83  	return
    84  }
    85  
    86  func resourceArmStorageContainerCreate(d *schema.ResourceData, meta interface{}) error {
    87  	armClient := meta.(*ArmClient)
    88  
    89  	resourceGroupName := d.Get("resource_group_name").(string)
    90  	storageAccountName := d.Get("storage_account_name").(string)
    91  
    92  	blobClient, accountExists, err := armClient.getBlobStorageClientForStorageAccount(resourceGroupName, storageAccountName)
    93  	if err != nil {
    94  		return err
    95  	}
    96  	if !accountExists {
    97  		return fmt.Errorf("Storage Account %q Not Found", storageAccountName)
    98  	}
    99  
   100  	name := d.Get("name").(string)
   101  
   102  	var accessType storage.ContainerAccessType
   103  	if d.Get("container_access_type").(string) == "private" {
   104  		accessType = storage.ContainerAccessType("")
   105  	} else {
   106  		accessType = storage.ContainerAccessType(d.Get("container_access_type").(string))
   107  	}
   108  
   109  	log.Printf("[INFO] Creating container %q in storage account %q.", name, storageAccountName)
   110  	_, err = blobClient.CreateContainerIfNotExists(name, accessType)
   111  	if err != nil {
   112  		return fmt.Errorf("Error creating container %q in storage account %q: %s", name, storageAccountName, err)
   113  	}
   114  
   115  	d.SetId(name)
   116  	return resourceArmStorageContainerRead(d, meta)
   117  }
   118  
   119  // resourceAzureStorageContainerRead does all the necessary API calls to
   120  // read the status of the storage container off Azure.
   121  func resourceArmStorageContainerRead(d *schema.ResourceData, meta interface{}) error {
   122  	armClient := meta.(*ArmClient)
   123  
   124  	resourceGroupName := d.Get("resource_group_name").(string)
   125  	storageAccountName := d.Get("storage_account_name").(string)
   126  
   127  	blobClient, accountExists, err := armClient.getBlobStorageClientForStorageAccount(resourceGroupName, storageAccountName)
   128  	if err != nil {
   129  		return err
   130  	}
   131  	if !accountExists {
   132  		log.Printf("[DEBUG] Storage account %q not found, removing container %q from state", storageAccountName, d.Id())
   133  		d.SetId("")
   134  		return nil
   135  	}
   136  
   137  	name := d.Get("name").(string)
   138  	containers, err := blobClient.ListContainers(storage.ListContainersParameters{
   139  		Prefix:  name,
   140  		Timeout: 90,
   141  	})
   142  	if err != nil {
   143  		return fmt.Errorf("Failed to retrieve storage containers in account %q: %s", name, err)
   144  	}
   145  
   146  	var found bool
   147  	for _, cont := range containers.Containers {
   148  		if cont.Name == name {
   149  			found = true
   150  
   151  			props := make(map[string]interface{})
   152  			props["last_modified"] = cont.Properties.LastModified
   153  			props["lease_status"] = cont.Properties.LeaseStatus
   154  			props["lease_state"] = cont.Properties.LeaseState
   155  			props["lease_duration"] = cont.Properties.LeaseDuration
   156  
   157  			d.Set("properties", props)
   158  		}
   159  	}
   160  
   161  	if !found {
   162  		log.Printf("[INFO] Storage container %q does not exist in account %q, removing from state...", name, storageAccountName)
   163  		d.SetId("")
   164  	}
   165  
   166  	return nil
   167  }
   168  
   169  func resourceArmStorageContainerExists(d *schema.ResourceData, meta interface{}) (bool, error) {
   170  	armClient := meta.(*ArmClient)
   171  
   172  	resourceGroupName := d.Get("resource_group_name").(string)
   173  	storageAccountName := d.Get("storage_account_name").(string)
   174  
   175  	blobClient, accountExists, err := armClient.getBlobStorageClientForStorageAccount(resourceGroupName, storageAccountName)
   176  	if err != nil {
   177  		return false, err
   178  	}
   179  	if !accountExists {
   180  		log.Printf("[DEBUG] Storage account %q not found, removing container %q from state", storageAccountName, d.Id())
   181  		d.SetId("")
   182  		return false, nil
   183  	}
   184  
   185  	name := d.Get("name").(string)
   186  
   187  	log.Printf("[INFO] Checking existence of storage container %q in storage account %q", name, storageAccountName)
   188  	exists, err := blobClient.ContainerExists(name)
   189  	if err != nil {
   190  		return false, fmt.Errorf("Error querying existence of storage container %q in storage account %q: %s", name, storageAccountName, err)
   191  	}
   192  
   193  	if !exists {
   194  		log.Printf("[INFO] Storage container %q does not exist in account %q, removing from state...", name, storageAccountName)
   195  		d.SetId("")
   196  	}
   197  
   198  	return exists, nil
   199  }
   200  
   201  // resourceAzureStorageContainerDelete does all the necessary API calls to
   202  // delete a storage container off Azure.
   203  func resourceArmStorageContainerDelete(d *schema.ResourceData, meta interface{}) error {
   204  	armClient := meta.(*ArmClient)
   205  
   206  	resourceGroupName := d.Get("resource_group_name").(string)
   207  	storageAccountName := d.Get("storage_account_name").(string)
   208  
   209  	blobClient, accountExists, err := armClient.getBlobStorageClientForStorageAccount(resourceGroupName, storageAccountName)
   210  	if err != nil {
   211  		return err
   212  	}
   213  	if !accountExists {
   214  		log.Printf("[INFO]Storage Account %q doesn't exist so the container won't exist", storageAccountName)
   215  		return nil
   216  	}
   217  
   218  	name := d.Get("name").(string)
   219  
   220  	log.Printf("[INFO] Deleting storage container %q in account %q", name, storageAccountName)
   221  	if _, err := blobClient.DeleteContainerIfExists(name); err != nil {
   222  		return fmt.Errorf("Error deleting storage container %q from storage account %q: %s", name, storageAccountName, err)
   223  	}
   224  
   225  	d.SetId("")
   226  	return nil
   227  }