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 }