github.com/jsoriano/terraform@v0.6.7-0.20151026070445-8b70867fdd95/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  }