terraform/builtin/providers/aws/autoscaling_tags.go

185 lines
4.9 KiB
Go
Raw Normal View History

2015-03-03 23:36:25 +01:00
package aws
import (
"bytes"
"fmt"
"log"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/autoscaling"
2015-03-03 23:36:25 +01:00
"github.com/hashicorp/terraform/helper/hashcode"
"github.com/hashicorp/terraform/helper/schema"
)
// tagsSchema returns the schema to use for tags.
func autoscalingTagsSchema() *schema.Schema {
return &schema.Schema{
Type: schema.TypeSet,
Optional: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"key": &schema.Schema{
Type: schema.TypeString,
Required: true,
},
"value": &schema.Schema{
Type: schema.TypeString,
Required: true,
},
"propagate_at_launch": &schema.Schema{
Type: schema.TypeBool,
Required: true,
},
},
},
Set: autoscalingTagsToHash,
}
}
func autoscalingTagsToHash(v interface{}) int {
var buf bytes.Buffer
m := v.(map[string]interface{})
buf.WriteString(fmt.Sprintf("%s-", m["key"].(string)))
buf.WriteString(fmt.Sprintf("%s-", m["value"].(string)))
buf.WriteString(fmt.Sprintf("%t-", m["propagate_at_launch"].(bool)))
return hashcode.String(buf.String())
}
// setTags is a helper to set the tags for a resource. It expects the
// tags field to be named "tag"
func setAutoscalingTags(conn *autoscaling.AutoScaling, d *schema.ResourceData) error {
if d.HasChange("tag") {
oraw, nraw := d.GetChange("tag")
o := setToMapByKey(oraw.(*schema.Set), "key")
n := setToMapByKey(nraw.(*schema.Set), "key")
resourceID := d.Get("name").(string)
c, r := diffAutoscalingTags(
autoscalingTagsFromMap(o, resourceID),
autoscalingTagsFromMap(n, resourceID),
resourceID)
2015-04-15 22:30:35 +02:00
create := autoscaling.CreateOrUpdateTagsInput{
2015-03-03 23:36:25 +01:00
Tags: c,
}
2015-04-15 22:30:35 +02:00
remove := autoscaling.DeleteTagsInput{
2015-03-03 23:36:25 +01:00
Tags: r,
}
// Set tags
if len(r) > 0 {
log.Printf("[DEBUG] Removing autoscaling tags: %#v", r)
2015-04-15 22:30:35 +02:00
if _, err := conn.DeleteTags(&remove); err != nil {
2015-03-03 23:36:25 +01:00
return err
}
}
if len(c) > 0 {
log.Printf("[DEBUG] Creating autoscaling tags: %#v", c)
2015-04-15 22:30:35 +02:00
if _, err := conn.CreateOrUpdateTags(&create); err != nil {
2015-03-03 23:36:25 +01:00
return err
}
}
}
return nil
}
// diffTags takes our tags locally and the ones remotely and returns
// the set of tags that must be created, and the set of tags that must
// be destroyed.
func diffAutoscalingTags(oldTags, newTags []*autoscaling.Tag, resourceID string) ([]*autoscaling.Tag, []*autoscaling.Tag) {
2015-03-03 23:36:25 +01:00
// First, we're creating everything we have
create := make(map[string]interface{})
for _, t := range newTags {
tag := map[string]interface{}{
"value": *t.Value,
"propagate_at_launch": *t.PropagateAtLaunch,
}
create[*t.Key] = tag
}
// Build the list of what to remove
2015-04-15 22:30:35 +02:00
var remove []*autoscaling.Tag
2015-03-03 23:36:25 +01:00
for _, t := range oldTags {
old, ok := create[*t.Key].(map[string]interface{})
if !ok || old["value"] != *t.Value || old["propagate_at_launch"] != *t.PropagateAtLaunch {
// Delete it!
remove = append(remove, t)
}
}
return autoscalingTagsFromMap(create, resourceID), remove
}
// tagsFromMap returns the tags for the given map of data.
func autoscalingTagsFromMap(m map[string]interface{}, resourceID string) []*autoscaling.Tag {
2015-04-15 22:30:35 +02:00
result := make([]*autoscaling.Tag, 0, len(m))
2015-03-03 23:36:25 +01:00
for k, v := range m {
attr := v.(map[string]interface{})
2015-04-15 22:30:35 +02:00
result = append(result, &autoscaling.Tag{
2015-03-03 23:36:25 +01:00
Key: aws.String(k),
Value: aws.String(attr["value"].(string)),
PropagateAtLaunch: aws.Bool(attr["propagate_at_launch"].(bool)),
ResourceId: aws.String(resourceID),
2015-03-03 23:36:25 +01:00
ResourceType: aws.String("auto-scaling-group"),
})
}
return result
}
// autoscalingTagsToMap turns the list of tags into a map.
func autoscalingTagsToMap(ts []*autoscaling.Tag) map[string]interface{} {
2015-03-03 23:36:25 +01:00
tags := make(map[string]interface{})
for _, t := range ts {
tag := map[string]interface{}{
"value": *t.Value,
"propagate_at_launch": *t.PropagateAtLaunch,
}
tags[*t.Key] = tag
}
return tags
}
// autoscalingTagDescriptionsToMap turns the list of tags into a map.
func autoscalingTagDescriptionsToMap(ts *[]*autoscaling.TagDescription) map[string]map[string]interface{} {
2015-03-03 23:36:25 +01:00
tags := make(map[string]map[string]interface{})
2015-04-15 22:30:35 +02:00
for _, t := range *ts {
2015-03-03 23:36:25 +01:00
tag := map[string]interface{}{
"value": *t.Value,
"propagate_at_launch": *t.PropagateAtLaunch,
2015-03-03 23:36:25 +01:00
}
tags[*t.Key] = tag
}
return tags
}
// autoscalingTagDescriptionsToSlice turns the list of tags into a slice.
func autoscalingTagDescriptionsToSlice(ts []*autoscaling.TagDescription) []map[string]interface{} {
tags := make([]map[string]interface{}, 0, len(ts))
for _, t := range ts {
tags = append(tags, map[string]interface{}{
"key": *t.Key,
"value": *t.Value,
"propagate_at_launch": *t.PropagateAtLaunch,
})
}
return tags
}
2015-03-03 23:36:25 +01:00
func setToMapByKey(s *schema.Set, key string) map[string]interface{} {
result := make(map[string]interface{})
for _, rawData := range s.List() {
data := rawData.(map[string]interface{})
result[data[key].(string)] = data
}
return result
}