github.com/memsql/terraform@v0.7.0-rc2.0.20160706152241-21e2173e0a32/builtin/providers/azurerm/resource_arm_storage_account.go (about)

     1  package azurerm
     2  
     3  import (
     4  	"fmt"
     5  	"net/http"
     6  	"regexp"
     7  	"strings"
     8  
     9  	"github.com/Azure/azure-sdk-for-go/arm/storage"
    10  	"github.com/hashicorp/terraform/helper/schema"
    11  )
    12  
    13  func resourceArmStorageAccount() *schema.Resource {
    14  	return &schema.Resource{
    15  		Create: resourceArmStorageAccountCreate,
    16  		Read:   resourceArmStorageAccountRead,
    17  		Update: resourceArmStorageAccountUpdate,
    18  		Delete: resourceArmStorageAccountDelete,
    19  
    20  		Schema: map[string]*schema.Schema{
    21  			"name": {
    22  				Type:         schema.TypeString,
    23  				Required:     true,
    24  				ForceNew:     true,
    25  				ValidateFunc: validateArmStorageAccountName,
    26  			},
    27  
    28  			"resource_group_name": {
    29  				Type:     schema.TypeString,
    30  				Required: true,
    31  				ForceNew: true,
    32  			},
    33  
    34  			"location": {
    35  				Type:      schema.TypeString,
    36  				Required:  true,
    37  				ForceNew:  true,
    38  				StateFunc: azureRMNormalizeLocation,
    39  			},
    40  
    41  			"account_type": {
    42  				Type:         schema.TypeString,
    43  				Required:     true,
    44  				ValidateFunc: validateArmStorageAccountType,
    45  			},
    46  
    47  			"primary_location": {
    48  				Type:     schema.TypeString,
    49  				Computed: true,
    50  			},
    51  
    52  			"secondary_location": {
    53  				Type:     schema.TypeString,
    54  				Computed: true,
    55  			},
    56  
    57  			"primary_blob_endpoint": {
    58  				Type:     schema.TypeString,
    59  				Computed: true,
    60  			},
    61  
    62  			"secondary_blob_endpoint": {
    63  				Type:     schema.TypeString,
    64  				Computed: true,
    65  			},
    66  
    67  			"primary_queue_endpoint": {
    68  				Type:     schema.TypeString,
    69  				Computed: true,
    70  			},
    71  
    72  			"secondary_queue_endpoint": {
    73  				Type:     schema.TypeString,
    74  				Computed: true,
    75  			},
    76  
    77  			"primary_table_endpoint": {
    78  				Type:     schema.TypeString,
    79  				Computed: true,
    80  			},
    81  
    82  			"secondary_table_endpoint": {
    83  				Type:     schema.TypeString,
    84  				Computed: true,
    85  			},
    86  
    87  			// NOTE: The API does not appear to expose a secondary file endpoint
    88  			"primary_file_endpoint": {
    89  				Type:     schema.TypeString,
    90  				Computed: true,
    91  			},
    92  
    93  			"primary_access_key": {
    94  				Type:     schema.TypeString,
    95  				Computed: true,
    96  			},
    97  
    98  			"secondary_access_key": {
    99  				Type:     schema.TypeString,
   100  				Computed: true,
   101  			},
   102  
   103  			"tags": tagsSchema(),
   104  		},
   105  	}
   106  }
   107  
   108  func resourceArmStorageAccountCreate(d *schema.ResourceData, meta interface{}) error {
   109  	client := meta.(*ArmClient).storageServiceClient
   110  
   111  	resourceGroupName := d.Get("resource_group_name").(string)
   112  	storageAccountName := d.Get("name").(string)
   113  	accountType := d.Get("account_type").(string)
   114  	location := d.Get("location").(string)
   115  	tags := d.Get("tags").(map[string]interface{})
   116  
   117  	sku := storage.Sku{
   118  		Name: storage.SkuName(accountType),
   119  	}
   120  
   121  	opts := storage.AccountCreateParameters{
   122  		Location: &location,
   123  		Sku:      &sku,
   124  		Tags:     expandTags(tags),
   125  	}
   126  
   127  	_, err := client.Create(resourceGroupName, storageAccountName, opts, make(chan struct{}))
   128  	if err != nil {
   129  		return fmt.Errorf("Error creating Azure Storage Account '%s': %s", storageAccountName, err)
   130  	}
   131  
   132  	// The only way to get the ID back apparently is to read the resource again
   133  	read, err := client.GetProperties(resourceGroupName, storageAccountName)
   134  	if err != nil {
   135  		return err
   136  	}
   137  	if read.ID == nil {
   138  		return fmt.Errorf("Cannot read Storage Account %s (resource group %s) ID",
   139  			storageAccountName, resourceGroupName)
   140  	}
   141  
   142  	d.SetId(*read.ID)
   143  
   144  	return resourceArmStorageAccountRead(d, meta)
   145  }
   146  
   147  // resourceArmStorageAccountUpdate is unusual in the ARM API where most resources have a combined
   148  // and idempotent operation for CreateOrUpdate. In particular updating all of the parameters
   149  // available requires a call to Update per parameter...
   150  func resourceArmStorageAccountUpdate(d *schema.ResourceData, meta interface{}) error {
   151  	client := meta.(*ArmClient).storageServiceClient
   152  	id, err := parseAzureResourceID(d.Id())
   153  	if err != nil {
   154  		return err
   155  	}
   156  	storageAccountName := id.Path["storageAccounts"]
   157  	resourceGroupName := id.ResourceGroup
   158  
   159  	d.Partial(true)
   160  
   161  	if d.HasChange("account_type") {
   162  		accountType := d.Get("account_type").(string)
   163  
   164  		sku := storage.Sku{
   165  			Name: storage.SkuName(accountType),
   166  		}
   167  
   168  		opts := storage.AccountUpdateParameters{
   169  			Sku: &sku,
   170  		}
   171  		_, err := client.Update(resourceGroupName, storageAccountName, opts)
   172  		if err != nil {
   173  			return fmt.Errorf("Error updating Azure Storage Account type %q: %s", storageAccountName, err)
   174  		}
   175  
   176  		d.SetPartial("account_type")
   177  	}
   178  
   179  	if d.HasChange("tags") {
   180  		tags := d.Get("tags").(map[string]interface{})
   181  
   182  		opts := storage.AccountUpdateParameters{
   183  			Tags: expandTags(tags),
   184  		}
   185  		_, err := client.Update(resourceGroupName, storageAccountName, opts)
   186  		if err != nil {
   187  			return fmt.Errorf("Error updating Azure Storage Account tags %q: %s", storageAccountName, err)
   188  		}
   189  
   190  		d.SetPartial("tags")
   191  	}
   192  
   193  	d.Partial(false)
   194  	return nil
   195  }
   196  
   197  func resourceArmStorageAccountRead(d *schema.ResourceData, meta interface{}) error {
   198  	client := meta.(*ArmClient).storageServiceClient
   199  
   200  	id, err := parseAzureResourceID(d.Id())
   201  	if err != nil {
   202  		return err
   203  	}
   204  	name := id.Path["storageAccounts"]
   205  	resGroup := id.ResourceGroup
   206  
   207  	resp, err := client.GetProperties(resGroup, name)
   208  	if err != nil {
   209  		if resp.StatusCode == http.StatusNotFound {
   210  			d.SetId("")
   211  			return nil
   212  		}
   213  
   214  		return fmt.Errorf("Error reading the state of AzureRM Storage Account %q: %s", name, err)
   215  	}
   216  
   217  	keys, err := client.ListKeys(resGroup, name)
   218  	if err != nil {
   219  		return err
   220  	}
   221  
   222  	accessKeys := *keys.Keys
   223  	d.Set("primary_access_key", accessKeys[0].KeyName)
   224  	d.Set("secondary_access_key", accessKeys[1].KeyName)
   225  	d.Set("location", resp.Location)
   226  	d.Set("account_type", resp.Sku.Name)
   227  	d.Set("primary_location", resp.Properties.PrimaryLocation)
   228  	d.Set("secondary_location", resp.Properties.SecondaryLocation)
   229  
   230  	if resp.Properties.PrimaryEndpoints != nil {
   231  		d.Set("primary_blob_endpoint", resp.Properties.PrimaryEndpoints.Blob)
   232  		d.Set("primary_queue_endpoint", resp.Properties.PrimaryEndpoints.Queue)
   233  		d.Set("primary_table_endpoint", resp.Properties.PrimaryEndpoints.Table)
   234  		d.Set("primary_file_endpoint", resp.Properties.PrimaryEndpoints.File)
   235  	}
   236  
   237  	if resp.Properties.SecondaryEndpoints != nil {
   238  		if resp.Properties.SecondaryEndpoints.Blob != nil {
   239  			d.Set("secondary_blob_endpoint", resp.Properties.SecondaryEndpoints.Blob)
   240  		} else {
   241  			d.Set("secondary_blob_endpoint", "")
   242  		}
   243  		if resp.Properties.SecondaryEndpoints.Queue != nil {
   244  			d.Set("secondary_queue_endpoint", resp.Properties.SecondaryEndpoints.Queue)
   245  		} else {
   246  			d.Set("secondary_queue_endpoint", "")
   247  		}
   248  		if resp.Properties.SecondaryEndpoints.Table != nil {
   249  			d.Set("secondary_table_endpoint", resp.Properties.SecondaryEndpoints.Table)
   250  		} else {
   251  			d.Set("secondary_table_endpoint", "")
   252  		}
   253  	}
   254  
   255  	flattenAndSetTags(d, resp.Tags)
   256  
   257  	return nil
   258  }
   259  
   260  func resourceArmStorageAccountDelete(d *schema.ResourceData, meta interface{}) error {
   261  	client := meta.(*ArmClient).storageServiceClient
   262  
   263  	id, err := parseAzureResourceID(d.Id())
   264  	if err != nil {
   265  		return err
   266  	}
   267  	name := id.Path["storageAccounts"]
   268  	resGroup := id.ResourceGroup
   269  
   270  	_, err = client.Delete(resGroup, name)
   271  	if err != nil {
   272  		return fmt.Errorf("Error issuing AzureRM delete request for storage account %q: %s", name, err)
   273  	}
   274  
   275  	return nil
   276  }
   277  
   278  func validateArmStorageAccountName(v interface{}, k string) (ws []string, es []error) {
   279  	input := v.(string)
   280  
   281  	if !regexp.MustCompile(`\A([a-z0-9]{3,24})\z`).MatchString(input) {
   282  		es = append(es, fmt.Errorf("name can only consist of lowercase letters and numbers, and must be between 3 and 24 characters long"))
   283  	}
   284  
   285  	return
   286  }
   287  
   288  func validateArmStorageAccountType(v interface{}, k string) (ws []string, es []error) {
   289  	validAccountTypes := []string{"standard_lrs", "standard_zrs",
   290  		"standard_grs", "standard_ragrs", "premium_lrs"}
   291  
   292  	input := strings.ToLower(v.(string))
   293  
   294  	for _, valid := range validAccountTypes {
   295  		if valid == input {
   296  			return
   297  		}
   298  	}
   299  
   300  	es = append(es, fmt.Errorf("Invalid storage account type %q", input))
   301  	return
   302  }