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