github.com/mohanarpit/terraform@v0.6.16-0.20160909104007-291f29853544/builtin/providers/aws/autoscaling_tags.go (about)

     1  package aws
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"log"
     7  
     8  	"github.com/aws/aws-sdk-go/aws"
     9  	"github.com/aws/aws-sdk-go/service/autoscaling"
    10  	"github.com/hashicorp/terraform/helper/hashcode"
    11  	"github.com/hashicorp/terraform/helper/schema"
    12  )
    13  
    14  // tagsSchema returns the schema to use for tags.
    15  func autoscalingTagsSchema() *schema.Schema {
    16  	return &schema.Schema{
    17  		Type:     schema.TypeSet,
    18  		Optional: true,
    19  		Elem: &schema.Resource{
    20  			Schema: map[string]*schema.Schema{
    21  				"key": &schema.Schema{
    22  					Type:     schema.TypeString,
    23  					Required: true,
    24  				},
    25  
    26  				"value": &schema.Schema{
    27  					Type:     schema.TypeString,
    28  					Required: true,
    29  				},
    30  
    31  				"propagate_at_launch": &schema.Schema{
    32  					Type:     schema.TypeBool,
    33  					Required: true,
    34  				},
    35  			},
    36  		},
    37  		Set: autoscalingTagsToHash,
    38  	}
    39  }
    40  
    41  func autoscalingTagsToHash(v interface{}) int {
    42  	var buf bytes.Buffer
    43  	m := v.(map[string]interface{})
    44  	buf.WriteString(fmt.Sprintf("%s-", m["key"].(string)))
    45  	buf.WriteString(fmt.Sprintf("%s-", m["value"].(string)))
    46  	buf.WriteString(fmt.Sprintf("%t-", m["propagate_at_launch"].(bool)))
    47  
    48  	return hashcode.String(buf.String())
    49  }
    50  
    51  // setTags is a helper to set the tags for a resource. It expects the
    52  // tags field to be named "tag"
    53  func setAutoscalingTags(conn *autoscaling.AutoScaling, d *schema.ResourceData) error {
    54  	if d.HasChange("tag") {
    55  		oraw, nraw := d.GetChange("tag")
    56  		o := setToMapByKey(oraw.(*schema.Set), "key")
    57  		n := setToMapByKey(nraw.(*schema.Set), "key")
    58  
    59  		resourceID := d.Get("name").(string)
    60  		c, r := diffAutoscalingTags(
    61  			autoscalingTagsFromMap(o, resourceID),
    62  			autoscalingTagsFromMap(n, resourceID),
    63  			resourceID)
    64  		create := autoscaling.CreateOrUpdateTagsInput{
    65  			Tags: c,
    66  		}
    67  		remove := autoscaling.DeleteTagsInput{
    68  			Tags: r,
    69  		}
    70  
    71  		// Set tags
    72  		if len(r) > 0 {
    73  			log.Printf("[DEBUG] Removing autoscaling tags: %#v", r)
    74  			if _, err := conn.DeleteTags(&remove); err != nil {
    75  				return err
    76  			}
    77  		}
    78  		if len(c) > 0 {
    79  			log.Printf("[DEBUG] Creating autoscaling tags: %#v", c)
    80  			if _, err := conn.CreateOrUpdateTags(&create); err != nil {
    81  				return err
    82  			}
    83  		}
    84  	}
    85  
    86  	return nil
    87  }
    88  
    89  // diffTags takes our tags locally and the ones remotely and returns
    90  // the set of tags that must be created, and the set of tags that must
    91  // be destroyed.
    92  func diffAutoscalingTags(oldTags, newTags []*autoscaling.Tag, resourceID string) ([]*autoscaling.Tag, []*autoscaling.Tag) {
    93  	// First, we're creating everything we have
    94  	create := make(map[string]interface{})
    95  	for _, t := range newTags {
    96  		tag := map[string]interface{}{
    97  			"value":               *t.Value,
    98  			"propagate_at_launch": *t.PropagateAtLaunch,
    99  		}
   100  		create[*t.Key] = tag
   101  	}
   102  
   103  	// Build the list of what to remove
   104  	var remove []*autoscaling.Tag
   105  	for _, t := range oldTags {
   106  		old, ok := create[*t.Key].(map[string]interface{})
   107  
   108  		if !ok || old["value"] != *t.Value || old["propagate_at_launch"] != *t.PropagateAtLaunch {
   109  			// Delete it!
   110  			remove = append(remove, t)
   111  		}
   112  	}
   113  
   114  	return autoscalingTagsFromMap(create, resourceID), remove
   115  }
   116  
   117  // tagsFromMap returns the tags for the given map of data.
   118  func autoscalingTagsFromMap(m map[string]interface{}, resourceID string) []*autoscaling.Tag {
   119  	result := make([]*autoscaling.Tag, 0, len(m))
   120  	for k, v := range m {
   121  		attr := v.(map[string]interface{})
   122  		result = append(result, &autoscaling.Tag{
   123  			Key:               aws.String(k),
   124  			Value:             aws.String(attr["value"].(string)),
   125  			PropagateAtLaunch: aws.Bool(attr["propagate_at_launch"].(bool)),
   126  			ResourceId:        aws.String(resourceID),
   127  			ResourceType:      aws.String("auto-scaling-group"),
   128  		})
   129  	}
   130  
   131  	return result
   132  }
   133  
   134  // autoscalingTagsToMap turns the list of tags into a map.
   135  func autoscalingTagsToMap(ts []*autoscaling.Tag) map[string]interface{} {
   136  	tags := make(map[string]interface{})
   137  	for _, t := range ts {
   138  		tag := map[string]interface{}{
   139  			"value":               *t.Value,
   140  			"propagate_at_launch": *t.PropagateAtLaunch,
   141  		}
   142  		tags[*t.Key] = tag
   143  	}
   144  
   145  	return tags
   146  }
   147  
   148  // autoscalingTagDescriptionsToMap turns the list of tags into a map.
   149  func autoscalingTagDescriptionsToMap(ts *[]*autoscaling.TagDescription) map[string]map[string]interface{} {
   150  	tags := make(map[string]map[string]interface{})
   151  	for _, t := range *ts {
   152  		tag := map[string]interface{}{
   153  			"value":               *t.Value,
   154  			"propagate_at_launch": *t.PropagateAtLaunch,
   155  		}
   156  		tags[*t.Key] = tag
   157  	}
   158  
   159  	return tags
   160  }
   161  
   162  // autoscalingTagDescriptionsToSlice turns the list of tags into a slice.
   163  func autoscalingTagDescriptionsToSlice(ts []*autoscaling.TagDescription) []map[string]interface{} {
   164  	tags := make([]map[string]interface{}, 0, len(ts))
   165  	for _, t := range ts {
   166  		tags = append(tags, map[string]interface{}{
   167  			"key":                 *t.Key,
   168  			"value":               *t.Value,
   169  			"propagate_at_launch": *t.PropagateAtLaunch,
   170  		})
   171  	}
   172  
   173  	return tags
   174  }
   175  
   176  func setToMapByKey(s *schema.Set, key string) map[string]interface{} {
   177  	result := make(map[string]interface{})
   178  	for _, rawData := range s.List() {
   179  		data := rawData.(map[string]interface{})
   180  		result[data[key].(string)] = data
   181  	}
   182  
   183  	return result
   184  }