github.com/mohanarpit/terraform@v0.6.16-0.20160909104007-291f29853544/builtin/providers/aws/resource_aws_glacier_vault.go (about) 1 package aws 2 3 import ( 4 "errors" 5 "fmt" 6 "log" 7 "regexp" 8 9 "github.com/hashicorp/terraform/helper/schema" 10 11 "github.com/aws/aws-sdk-go/aws" 12 "github.com/aws/aws-sdk-go/aws/awserr" 13 "github.com/aws/aws-sdk-go/service/glacier" 14 ) 15 16 func resourceAwsGlacierVault() *schema.Resource { 17 return &schema.Resource{ 18 Create: resourceAwsGlacierVaultCreate, 19 Read: resourceAwsGlacierVaultRead, 20 Update: resourceAwsGlacierVaultUpdate, 21 Delete: resourceAwsGlacierVaultDelete, 22 23 Importer: &schema.ResourceImporter{ 24 State: schema.ImportStatePassthrough, 25 }, 26 27 Schema: map[string]*schema.Schema{ 28 "name": &schema.Schema{ 29 Type: schema.TypeString, 30 Required: true, 31 ForceNew: true, 32 ValidateFunc: func(v interface{}, k string) (ws []string, errors []error) { 33 value := v.(string) 34 if !regexp.MustCompile(`^[.0-9A-Za-z-_]+$`).MatchString(value) { 35 errors = append(errors, fmt.Errorf( 36 "only alphanumeric characters, hyphens, underscores, and periods allowed in %q", k)) 37 } 38 if len(value) > 255 { 39 errors = append(errors, fmt.Errorf( 40 "%q cannot be longer than 255 characters", k)) 41 } 42 return 43 }, 44 }, 45 46 "location": &schema.Schema{ 47 Type: schema.TypeString, 48 Computed: true, 49 }, 50 51 "arn": &schema.Schema{ 52 Type: schema.TypeString, 53 Computed: true, 54 }, 55 56 "access_policy": &schema.Schema{ 57 Type: schema.TypeString, 58 Optional: true, 59 StateFunc: normalizeJson, 60 }, 61 62 "notification": &schema.Schema{ 63 Type: schema.TypeList, 64 Optional: true, 65 Elem: &schema.Resource{ 66 Schema: map[string]*schema.Schema{ 67 "events": &schema.Schema{ 68 Type: schema.TypeSet, 69 Required: true, 70 Elem: &schema.Schema{Type: schema.TypeString}, 71 Set: schema.HashString, 72 }, 73 "sns_topic": &schema.Schema{ 74 Type: schema.TypeString, 75 Required: true, 76 }, 77 }, 78 }, 79 }, 80 81 "tags": tagsSchema(), 82 }, 83 } 84 } 85 86 func resourceAwsGlacierVaultCreate(d *schema.ResourceData, meta interface{}) error { 87 glacierconn := meta.(*AWSClient).glacierconn 88 89 input := &glacier.CreateVaultInput{ 90 VaultName: aws.String(d.Get("name").(string)), 91 } 92 93 out, err := glacierconn.CreateVault(input) 94 if err != nil { 95 return fmt.Errorf("Error creating Glacier Vault: %s", err) 96 } 97 98 d.SetId(d.Get("name").(string)) 99 d.Set("location", *out.Location) 100 101 return resourceAwsGlacierVaultUpdate(d, meta) 102 } 103 104 func resourceAwsGlacierVaultUpdate(d *schema.ResourceData, meta interface{}) error { 105 glacierconn := meta.(*AWSClient).glacierconn 106 107 if err := setGlacierVaultTags(glacierconn, d); err != nil { 108 return err 109 } 110 111 if d.HasChange("access_policy") { 112 if err := resourceAwsGlacierVaultPolicyUpdate(glacierconn, d); err != nil { 113 return err 114 } 115 } 116 117 if d.HasChange("notification") { 118 if err := resourceAwsGlacierVaultNotificationUpdate(glacierconn, d); err != nil { 119 return err 120 } 121 } 122 123 return resourceAwsGlacierVaultRead(d, meta) 124 } 125 126 func resourceAwsGlacierVaultRead(d *schema.ResourceData, meta interface{}) error { 127 glacierconn := meta.(*AWSClient).glacierconn 128 129 input := &glacier.DescribeVaultInput{ 130 VaultName: aws.String(d.Id()), 131 } 132 133 out, err := glacierconn.DescribeVault(input) 134 if err != nil { 135 return fmt.Errorf("Error reading Glacier Vault: %s", err.Error()) 136 } 137 138 awsClient := meta.(*AWSClient) 139 d.Set("name", out.VaultName) 140 d.Set("arn", out.VaultARN) 141 142 location, err := buildGlacierVaultLocation(awsClient.accountid, d.Id()) 143 if err != nil { 144 return err 145 } 146 d.Set("location", location) 147 148 tags, err := getGlacierVaultTags(glacierconn, d.Id()) 149 if err != nil { 150 return err 151 } 152 d.Set("tags", tags) 153 154 log.Printf("[DEBUG] Getting the access_policy for Vault %s", d.Id()) 155 pol, err := glacierconn.GetVaultAccessPolicy(&glacier.GetVaultAccessPolicyInput{ 156 VaultName: aws.String(d.Id()), 157 }) 158 159 if awserr, ok := err.(awserr.Error); ok && awserr.Code() == "ResourceNotFoundException" { 160 d.Set("access_policy", "") 161 } else if pol != nil { 162 d.Set("access_policy", normalizeJson(*pol.Policy.Policy)) 163 } else { 164 return err 165 } 166 167 notifications, err := getGlacierVaultNotification(glacierconn, d.Id()) 168 if awserr, ok := err.(awserr.Error); ok && awserr.Code() == "ResourceNotFoundException" { 169 d.Set("notification", "") 170 } else if pol != nil { 171 d.Set("notification", notifications) 172 } else { 173 return err 174 } 175 176 return nil 177 } 178 179 func resourceAwsGlacierVaultDelete(d *schema.ResourceData, meta interface{}) error { 180 glacierconn := meta.(*AWSClient).glacierconn 181 182 log.Printf("[DEBUG] Glacier Delete Vault: %s", d.Id()) 183 _, err := glacierconn.DeleteVault(&glacier.DeleteVaultInput{ 184 VaultName: aws.String(d.Id()), 185 }) 186 if err != nil { 187 return fmt.Errorf("Error deleting Glacier Vault: %s", err.Error()) 188 } 189 return nil 190 } 191 192 func resourceAwsGlacierVaultNotificationUpdate(glacierconn *glacier.Glacier, d *schema.ResourceData) error { 193 194 if v, ok := d.GetOk("notification"); ok { 195 settings := v.([]interface{}) 196 197 if len(settings) > 1 { 198 return fmt.Errorf("Only a single Notification Block is allowed for Glacier Vault") 199 } else if len(settings) == 1 { 200 s := settings[0].(map[string]interface{}) 201 var events []*string 202 for _, id := range s["events"].(*schema.Set).List() { 203 events = append(events, aws.String(id.(string))) 204 } 205 206 _, err := glacierconn.SetVaultNotifications(&glacier.SetVaultNotificationsInput{ 207 VaultName: aws.String(d.Id()), 208 VaultNotificationConfig: &glacier.VaultNotificationConfig{ 209 SNSTopic: aws.String(s["sns_topic"].(string)), 210 Events: events, 211 }, 212 }) 213 214 if err != nil { 215 return fmt.Errorf("Error Updating Glacier Vault Notifications: %s", err.Error()) 216 } 217 } 218 } else { 219 _, err := glacierconn.DeleteVaultNotifications(&glacier.DeleteVaultNotificationsInput{ 220 VaultName: aws.String(d.Id()), 221 }) 222 223 if err != nil { 224 return fmt.Errorf("Error Removing Glacier Vault Notifications: %s", err.Error()) 225 } 226 227 } 228 229 return nil 230 } 231 232 func resourceAwsGlacierVaultPolicyUpdate(glacierconn *glacier.Glacier, d *schema.ResourceData) error { 233 vaultName := d.Id() 234 policyContents := d.Get("access_policy").(string) 235 236 policy := &glacier.VaultAccessPolicy{ 237 Policy: aws.String(policyContents), 238 } 239 240 if policyContents != "" { 241 log.Printf("[DEBUG] Glacier Vault: %s, put policy", vaultName) 242 243 _, err := glacierconn.SetVaultAccessPolicy(&glacier.SetVaultAccessPolicyInput{ 244 VaultName: aws.String(d.Id()), 245 Policy: policy, 246 }) 247 248 if err != nil { 249 return fmt.Errorf("Error putting Glacier Vault policy: %s", err.Error()) 250 } 251 } else { 252 log.Printf("[DEBUG] Glacier Vault: %s, delete policy: %s", vaultName, policy) 253 _, err := glacierconn.DeleteVaultAccessPolicy(&glacier.DeleteVaultAccessPolicyInput{ 254 VaultName: aws.String(d.Id()), 255 }) 256 257 if err != nil { 258 return fmt.Errorf("Error deleting Glacier Vault policy: %s", err.Error()) 259 } 260 } 261 262 return nil 263 } 264 265 func setGlacierVaultTags(conn *glacier.Glacier, d *schema.ResourceData) error { 266 if d.HasChange("tags") { 267 oraw, nraw := d.GetChange("tags") 268 o := oraw.(map[string]interface{}) 269 n := nraw.(map[string]interface{}) 270 create, remove := diffGlacierVaultTags(mapGlacierVaultTags(o), mapGlacierVaultTags(n)) 271 272 // Set tags 273 if len(remove) > 0 { 274 tagsToRemove := &glacier.RemoveTagsFromVaultInput{ 275 VaultName: aws.String(d.Id()), 276 TagKeys: glacierStringsToPointyString(remove), 277 } 278 279 log.Printf("[DEBUG] Removing tags: from %s", d.Id()) 280 _, err := conn.RemoveTagsFromVault(tagsToRemove) 281 if err != nil { 282 return err 283 } 284 } 285 if len(create) > 0 { 286 tagsToAdd := &glacier.AddTagsToVaultInput{ 287 VaultName: aws.String(d.Id()), 288 Tags: glacierVaultTagsFromMap(create), 289 } 290 291 log.Printf("[DEBUG] Creating tags: for %s", d.Id()) 292 _, err := conn.AddTagsToVault(tagsToAdd) 293 if err != nil { 294 return err 295 } 296 } 297 } 298 299 return nil 300 } 301 302 func mapGlacierVaultTags(m map[string]interface{}) map[string]string { 303 results := make(map[string]string) 304 for k, v := range m { 305 results[k] = v.(string) 306 } 307 308 return results 309 } 310 311 func diffGlacierVaultTags(oldTags, newTags map[string]string) (map[string]string, []string) { 312 313 create := make(map[string]string) 314 for k, v := range newTags { 315 create[k] = v 316 } 317 318 // Build the list of what to remove 319 var remove []string 320 for k, v := range oldTags { 321 old, ok := create[k] 322 if !ok || old != v { 323 // Delete it! 324 remove = append(remove, k) 325 } 326 } 327 328 return create, remove 329 } 330 331 func getGlacierVaultTags(glacierconn *glacier.Glacier, vaultName string) (map[string]string, error) { 332 request := &glacier.ListTagsForVaultInput{ 333 VaultName: aws.String(vaultName), 334 } 335 336 log.Printf("[DEBUG] Getting the tags: for %s", vaultName) 337 response, err := glacierconn.ListTagsForVault(request) 338 if awserr, ok := err.(awserr.Error); ok && awserr.Code() == "NoSuchTagSet" { 339 return map[string]string{}, nil 340 } else if err != nil { 341 return nil, err 342 } 343 344 return glacierVaultTagsToMap(response.Tags), nil 345 } 346 347 func glacierVaultTagsToMap(responseTags map[string]*string) map[string]string { 348 results := make(map[string]string, len(responseTags)) 349 for k, v := range responseTags { 350 results[k] = *v 351 } 352 353 return results 354 } 355 356 func glacierVaultTagsFromMap(responseTags map[string]string) map[string]*string { 357 results := make(map[string]*string, len(responseTags)) 358 for k, v := range responseTags { 359 results[k] = aws.String(v) 360 } 361 362 return results 363 } 364 365 func glacierStringsToPointyString(s []string) []*string { 366 results := make([]*string, len(s)) 367 for i, x := range s { 368 results[i] = aws.String(x) 369 } 370 371 return results 372 } 373 374 func glacierPointersToStringList(pointers []*string) []interface{} { 375 list := make([]interface{}, len(pointers)) 376 for i, v := range pointers { 377 list[i] = *v 378 } 379 return list 380 } 381 382 func buildGlacierVaultLocation(accountId, vaultName string) (string, error) { 383 if accountId == "" { 384 return "", errors.New("AWS account ID unavailable - failed to construct Vault location") 385 } 386 return fmt.Sprintf("/" + accountId + "/vaults/" + vaultName), nil 387 } 388 389 func getGlacierVaultNotification(glacierconn *glacier.Glacier, vaultName string) ([]map[string]interface{}, error) { 390 request := &glacier.GetVaultNotificationsInput{ 391 VaultName: aws.String(vaultName), 392 } 393 394 response, err := glacierconn.GetVaultNotifications(request) 395 if err != nil { 396 return nil, fmt.Errorf("Error reading Glacier Vault Notifications: %s", err.Error()) 397 } 398 399 notifications := make(map[string]interface{}, 0) 400 401 log.Print("[DEBUG] Flattening Glacier Vault Notifications") 402 403 notifications["events"] = schema.NewSet(schema.HashString, glacierPointersToStringList(response.VaultNotificationConfig.Events)) 404 notifications["sns_topic"] = *response.VaultNotificationConfig.SNSTopic 405 406 return []map[string]interface{}{notifications}, nil 407 }