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  }