github.com/gabrielperezs/terraform@v0.7.0-rc2.0.20160715084931-f7da2612946f/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 }