github.com/sarguru/terraform@v0.6.17-0.20160525232901-8fcdfd7e3dc9/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  			"primary_access_key": &schema.Schema{
    94  				Type:     schema.TypeString,
    95  				Computed: true,
    96  			},
    97  
    98  			"secondary_access_key": &schema.Schema{
    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  	accResp, err := client.Create(resourceGroupName, storageAccountName, opts)
   126  	if err != nil {
   127  		return fmt.Errorf("Error creating Azure Storage Account '%s': %s", storageAccountName, err)
   128  	}
   129  	_, err = pollIndefinitelyAsNeeded(client.Client, accResp.Response.Response, http.StatusOK)
   130  	if err != nil {
   131  		return fmt.Errorf("Error creating Azure Storage Account %q: %s", storageAccountName, err)
   132  	}
   133  
   134  	// The only way to get the ID back apparently is to read the resource again
   135  	account, err := client.GetProperties(resourceGroupName, storageAccountName)
   136  	if err != nil {
   137  		return fmt.Errorf("Error retrieving Azure Storage Account %q: %s", storageAccountName, err)
   138  	}
   139  
   140  	d.SetId(*account.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  		accResp, 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  		_, err = pollIndefinitelyAsNeeded(client.Client, accResp.Response.Response, http.StatusOK)
   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  		accResp, 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  		_, err = pollIndefinitelyAsNeeded(client.Client, accResp.Response.Response, http.StatusOK)
   190  		if err != nil {
   191  			return fmt.Errorf("Error updating Azure Storage Account tags %q: %s", storageAccountName, err)
   192  		}
   193  
   194  		d.SetPartial("tags")
   195  	}
   196  
   197  	d.Partial(false)
   198  	return nil
   199  }
   200  
   201  func resourceArmStorageAccountRead(d *schema.ResourceData, meta interface{}) error {
   202  	client := meta.(*ArmClient).storageServiceClient
   203  
   204  	id, err := parseAzureResourceID(d.Id())
   205  	if err != nil {
   206  		return err
   207  	}
   208  	name := id.Path["storageAccounts"]
   209  	resGroup := id.ResourceGroup
   210  
   211  	resp, err := client.GetProperties(resGroup, name)
   212  	if err != nil {
   213  		if resp.StatusCode == http.StatusNotFound {
   214  			d.SetId("")
   215  			return nil
   216  		}
   217  
   218  		return fmt.Errorf("Error reading the state of AzureRM Storage Account %q: %s", name, err)
   219  	}
   220  
   221  	keys, err := client.ListKeys(resGroup, name)
   222  	if err != nil {
   223  		return err
   224  	}
   225  
   226  	d.Set("primary_access_key", keys.Key1)
   227  	d.Set("secondary_access_key", keys.Key2)
   228  	d.Set("location", resp.Location)
   229  	d.Set("account_type", resp.Properties.AccountType)
   230  	d.Set("primary_location", resp.Properties.PrimaryLocation)
   231  	d.Set("secondary_location", resp.Properties.SecondaryLocation)
   232  
   233  	if resp.Properties.PrimaryEndpoints != nil {
   234  		d.Set("primary_blob_endpoint", resp.Properties.PrimaryEndpoints.Blob)
   235  		d.Set("primary_queue_endpoint", resp.Properties.PrimaryEndpoints.Queue)
   236  		d.Set("primary_table_endpoint", resp.Properties.PrimaryEndpoints.Table)
   237  		d.Set("primary_file_endpoint", resp.Properties.PrimaryEndpoints.File)
   238  	}
   239  
   240  	if resp.Properties.SecondaryEndpoints != nil {
   241  		if resp.Properties.SecondaryEndpoints.Blob != nil {
   242  			d.Set("secondary_blob_endpoint", resp.Properties.SecondaryEndpoints.Blob)
   243  		} else {
   244  			d.Set("secondary_blob_endpoint", "")
   245  		}
   246  		if resp.Properties.SecondaryEndpoints.Queue != nil {
   247  			d.Set("secondary_queue_endpoint", resp.Properties.SecondaryEndpoints.Queue)
   248  		} else {
   249  			d.Set("secondary_queue_endpoint", "")
   250  		}
   251  		if resp.Properties.SecondaryEndpoints.Table != nil {
   252  			d.Set("secondary_table_endpoint", resp.Properties.SecondaryEndpoints.Table)
   253  		} else {
   254  			d.Set("secondary_table_endpoint", "")
   255  		}
   256  	}
   257  
   258  	flattenAndSetTags(d, resp.Tags)
   259  
   260  	return nil
   261  }
   262  
   263  func resourceArmStorageAccountDelete(d *schema.ResourceData, meta interface{}) error {
   264  	client := meta.(*ArmClient).storageServiceClient
   265  
   266  	id, err := parseAzureResourceID(d.Id())
   267  	if err != nil {
   268  		return err
   269  	}
   270  	name := id.Path["storageAccounts"]
   271  	resGroup := id.ResourceGroup
   272  
   273  	accResp, err := client.Delete(resGroup, name)
   274  	if err != nil {
   275  		return fmt.Errorf("Error issuing AzureRM delete request for storage account %q: %s", name, err)
   276  	}
   277  	_, err = pollIndefinitelyAsNeeded(client.Client, accResp.Response, http.StatusNotFound)
   278  	if err != nil {
   279  		return fmt.Errorf("Error polling for AzureRM delete request for storage account %q: %s", name, err)
   280  	}
   281  
   282  	return nil
   283  }
   284  
   285  func validateArmStorageAccountName(v interface{}, k string) (ws []string, es []error) {
   286  	input := v.(string)
   287  
   288  	if !regexp.MustCompile(`\A([a-z0-9]{3,24})\z`).MatchString(input) {
   289  		es = append(es, fmt.Errorf("name can only consist of lowercase letters and numbers, and must be between 3 and 24 characters long"))
   290  	}
   291  
   292  	return
   293  }
   294  
   295  func validateArmStorageAccountType(v interface{}, k string) (ws []string, es []error) {
   296  	validAccountTypes := []string{"standard_lrs", "standard_zrs",
   297  		"standard_grs", "standard_ragrs", "premium_lrs"}
   298  
   299  	input := strings.ToLower(v.(string))
   300  
   301  	for _, valid := range validAccountTypes {
   302  		if valid == input {
   303  			return
   304  		}
   305  	}
   306  
   307  	es = append(es, fmt.Errorf("Invalid storage account type %q", input))
   308  	return
   309  }