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