github.com/danrjohnson/terraform@v0.7.0-rc2.0.20160627135212-d0fc1fa086ff/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  	opts := storage.AccountCreateParameters{
   118  		Location: &location,
   119  		Properties: &storage.AccountPropertiesCreateParameters{
   120  			AccountType: storage.AccountType(accountType),
   121  		},
   122  		Tags: expandTags(tags),
   123  	}
   124  
   125  	_, err := client.Create(resourceGroupName, storageAccountName, opts, make(chan struct{}))
   126  	if err != nil {
   127  		return fmt.Errorf("Error creating Azure Storage Account '%s': %s", storageAccountName, err)
   128  	}
   129  
   130  	// The only way to get the ID back apparently is to read the resource again
   131  	read, err := client.GetProperties(resourceGroupName, storageAccountName)
   132  	if err != nil {
   133  		return err
   134  	}
   135  	if read.ID == nil {
   136  		return fmt.Errorf("Cannot read Storage Account %s (resource group %s) ID",
   137  			storageAccountName, resourceGroupName)
   138  	}
   139  
   140  	d.SetId(*read.ID)
   141  
   142  	return resourceArmStorageAccountRead(d, meta)
   143  }
   144  
   145  // resourceArmStorageAccountUpdate is unusual in the ARM API where most resources have a combined
   146  // and idempotent operation for CreateOrUpdate. In particular updating all of the parameters
   147  // available requires a call to Update per parameter...
   148  func resourceArmStorageAccountUpdate(d *schema.ResourceData, meta interface{}) error {
   149  	client := meta.(*ArmClient).storageServiceClient
   150  	id, err := parseAzureResourceID(d.Id())
   151  	if err != nil {
   152  		return err
   153  	}
   154  	storageAccountName := id.Path["storageAccounts"]
   155  	resourceGroupName := id.ResourceGroup
   156  
   157  	d.Partial(true)
   158  
   159  	if d.HasChange("account_type") {
   160  		accountType := d.Get("account_type").(string)
   161  
   162  		opts := storage.AccountUpdateParameters{
   163  			Properties: &storage.AccountPropertiesUpdateParameters{
   164  				AccountType: storage.AccountType(accountType),
   165  			},
   166  		}
   167  		_, err := client.Update(resourceGroupName, storageAccountName, opts)
   168  		if err != nil {
   169  			return fmt.Errorf("Error updating Azure Storage Account type %q: %s", storageAccountName, err)
   170  		}
   171  
   172  		d.SetPartial("account_type")
   173  	}
   174  
   175  	if d.HasChange("tags") {
   176  		tags := d.Get("tags").(map[string]interface{})
   177  
   178  		opts := storage.AccountUpdateParameters{
   179  			Tags: expandTags(tags),
   180  		}
   181  		_, err := client.Update(resourceGroupName, storageAccountName, opts)
   182  		if err != nil {
   183  			return fmt.Errorf("Error updating Azure Storage Account tags %q: %s", storageAccountName, err)
   184  		}
   185  
   186  		d.SetPartial("tags")
   187  	}
   188  
   189  	d.Partial(false)
   190  	return nil
   191  }
   192  
   193  func resourceArmStorageAccountRead(d *schema.ResourceData, meta interface{}) error {
   194  	client := meta.(*ArmClient).storageServiceClient
   195  
   196  	id, err := parseAzureResourceID(d.Id())
   197  	if err != nil {
   198  		return err
   199  	}
   200  	name := id.Path["storageAccounts"]
   201  	resGroup := id.ResourceGroup
   202  
   203  	resp, err := client.GetProperties(resGroup, name)
   204  	if err != nil {
   205  		if resp.StatusCode == http.StatusNotFound {
   206  			d.SetId("")
   207  			return nil
   208  		}
   209  
   210  		return fmt.Errorf("Error reading the state of AzureRM Storage Account %q: %s", name, err)
   211  	}
   212  
   213  	keys, err := client.ListKeys(resGroup, name)
   214  	if err != nil {
   215  		return err
   216  	}
   217  
   218  	d.Set("primary_access_key", keys.Key1)
   219  	d.Set("secondary_access_key", keys.Key2)
   220  	d.Set("location", resp.Location)
   221  	d.Set("account_type", resp.Properties.AccountType)
   222  	d.Set("primary_location", resp.Properties.PrimaryLocation)
   223  	d.Set("secondary_location", resp.Properties.SecondaryLocation)
   224  
   225  	if resp.Properties.PrimaryEndpoints != nil {
   226  		d.Set("primary_blob_endpoint", resp.Properties.PrimaryEndpoints.Blob)
   227  		d.Set("primary_queue_endpoint", resp.Properties.PrimaryEndpoints.Queue)
   228  		d.Set("primary_table_endpoint", resp.Properties.PrimaryEndpoints.Table)
   229  		d.Set("primary_file_endpoint", resp.Properties.PrimaryEndpoints.File)
   230  	}
   231  
   232  	if resp.Properties.SecondaryEndpoints != nil {
   233  		if resp.Properties.SecondaryEndpoints.Blob != nil {
   234  			d.Set("secondary_blob_endpoint", resp.Properties.SecondaryEndpoints.Blob)
   235  		} else {
   236  			d.Set("secondary_blob_endpoint", "")
   237  		}
   238  		if resp.Properties.SecondaryEndpoints.Queue != nil {
   239  			d.Set("secondary_queue_endpoint", resp.Properties.SecondaryEndpoints.Queue)
   240  		} else {
   241  			d.Set("secondary_queue_endpoint", "")
   242  		}
   243  		if resp.Properties.SecondaryEndpoints.Table != nil {
   244  			d.Set("secondary_table_endpoint", resp.Properties.SecondaryEndpoints.Table)
   245  		} else {
   246  			d.Set("secondary_table_endpoint", "")
   247  		}
   248  	}
   249  
   250  	flattenAndSetTags(d, resp.Tags)
   251  
   252  	return nil
   253  }
   254  
   255  func resourceArmStorageAccountDelete(d *schema.ResourceData, meta interface{}) error {
   256  	client := meta.(*ArmClient).storageServiceClient
   257  
   258  	id, err := parseAzureResourceID(d.Id())
   259  	if err != nil {
   260  		return err
   261  	}
   262  	name := id.Path["storageAccounts"]
   263  	resGroup := id.ResourceGroup
   264  
   265  	_, err = client.Delete(resGroup, name)
   266  	if err != nil {
   267  		return fmt.Errorf("Error issuing AzureRM delete request for storage account %q: %s", name, err)
   268  	}
   269  
   270  	return nil
   271  }
   272  
   273  func validateArmStorageAccountName(v interface{}, k string) (ws []string, es []error) {
   274  	input := v.(string)
   275  
   276  	if !regexp.MustCompile(`\A([a-z0-9]{3,24})\z`).MatchString(input) {
   277  		es = append(es, fmt.Errorf("name can only consist of lowercase letters and numbers, and must be between 3 and 24 characters long"))
   278  	}
   279  
   280  	return
   281  }
   282  
   283  func validateArmStorageAccountType(v interface{}, k string) (ws []string, es []error) {
   284  	validAccountTypes := []string{"standard_lrs", "standard_zrs",
   285  		"standard_grs", "standard_ragrs", "premium_lrs"}
   286  
   287  	input := strings.ToLower(v.(string))
   288  
   289  	for _, valid := range validAccountTypes {
   290  		if valid == input {
   291  			return
   292  		}
   293  	}
   294  
   295  	es = append(es, fmt.Errorf("Invalid storage account type %q", input))
   296  	return
   297  }