From b18afaa5dbe6a49a448c68b4775df87297af94d2 Mon Sep 17 00:00:00 2001 From: Carles Figuerola Date: Tue, 19 Jan 2016 11:41:18 -0600 Subject: [PATCH] Add taging shared module for cloudstack and implement it in resource_network --- .../cloudstack/resource_cloudstack_network.go | 16 ++++ builtin/providers/cloudstack/tags.go | 81 +++++++++++++++++++ .../cloudstack/r/network.html.markdown | 2 + 3 files changed, 99 insertions(+) create mode 100644 builtin/providers/cloudstack/tags.go diff --git a/builtin/providers/cloudstack/resource_cloudstack_network.go b/builtin/providers/cloudstack/resource_cloudstack_network.go index a76beae32..b8b1d3d58 100644 --- a/builtin/providers/cloudstack/resource_cloudstack_network.go +++ b/builtin/providers/cloudstack/resource_cloudstack_network.go @@ -63,6 +63,8 @@ func resourceCloudStackNetwork() *schema.Resource { Required: true, ForceNew: true, }, + + "tags": tagsSchema(), }, } } @@ -144,6 +146,8 @@ func resourceCloudStackNetworkCreate(d *schema.ResourceData, meta interface{}) e d.SetId(r.Id) + setTags(cs, d, "network") + return resourceCloudStackNetworkRead(d, meta) } @@ -167,6 +171,13 @@ func resourceCloudStackNetworkRead(d *schema.ResourceData, meta interface{}) err d.Set("display_text", n.Displaytext) d.Set("cidr", n.Cidr) + // Read the tags and sort them on a map + tags := make(map[string]string) + for item := range n.Tags { + tags[n.Tags[item].Key] = n.Tags[item].Value + } + d.Set("tags", tags) + setValueOrID(d, "network_offering", n.Networkofferingname, n.Networkofferingid) setValueOrID(d, "project", n.Project, n.Projectid) setValueOrID(d, "zone", n.Zonename, n.Zoneid) @@ -216,6 +227,11 @@ func resourceCloudStackNetworkUpdate(d *schema.ResourceData, meta interface{}) e "Error updating network %s: %s", name, err) } + // Check if tags have changed + if d.HasChange("tags") { + setTags(cs, d, "network") + } + return resourceCloudStackNetworkRead(d, meta) } diff --git a/builtin/providers/cloudstack/tags.go b/builtin/providers/cloudstack/tags.go new file mode 100644 index 000000000..258785a4c --- /dev/null +++ b/builtin/providers/cloudstack/tags.go @@ -0,0 +1,81 @@ +package cloudstack + +import ( + "log" + + "github.com/hashicorp/terraform/helper/schema" + "github.com/xanzy/go-cloudstack/cloudstack" +) + +// tagsSchema returns the schema to use for tags. +// +func tagsSchema() *schema.Schema { + return &schema.Schema{ + Type: schema.TypeMap, + Optional: true, + } +} + +// setTags is a helper to set the tags for a resource. It expects the +// tags field to be named "tags" +func setTags(cs *cloudstack.CloudStackClient, d *schema.ResourceData, resourcetype string) error { + + if d.HasChange("tags") { + oraw, nraw := d.GetChange("tags") + o := oraw.(map[string]interface{}) + n := nraw.(map[string]interface{}) + create, remove := diffTags(tagsFromMap(o), tagsFromMap(n)) + log.Printf("[DEBUG] tags to remove: %s", remove) + log.Printf("[DEBUG] tags to create: %s", create) + + // Set tags + if len(remove) > 0 { + log.Printf("[DEBUG] Removing tags: %s from %s", remove, d.Id()) + p := cs.Resourcetags.NewDeleteTagsParams([]string{d.Id()}, resourcetype) + p.SetTags(remove) + _, err := cs.Resourcetags.DeleteTags(p) + if err != nil { + return err + } + } + if len(create) > 0 { + log.Printf("[DEBUG] Creating tags: %s for %s", create, d.Id()) + p := cs.Resourcetags.NewCreateTagsParams([]string{d.Id()}, resourcetype, create) + _, err := cs.Resourcetags.CreateTags(p) + if err != nil { + return err + } + } + } + + return nil +} + +// diffTags takes our tags locally and the ones remotely and returns +// the set of tags that must be destroyed, and the set of tags that must +// be created. +func diffTags(oldTags, newTags map[string]string) (map[string]string, map[string]string) { + remove := make(map[string]string) + for k, v := range oldTags { + old, ok := newTags[k] + if !ok || old != v { + // Delete it! + remove[k] = v + } else { + // We need to remove the modified tags to create them again, + // but we should avoid creating what we already have + delete(newTags, k) + } + } + + return newTags, remove +} + +// tagsFromMap returns the tags for the given tags schema. +func tagsFromMap(m map[string]interface{}) map[string]string { + result := make(map[string]string, len(m)) + for k, v := range m { + result[k] = v.(string) + } + return result +} diff --git a/website/source/docs/providers/cloudstack/r/network.html.markdown b/website/source/docs/providers/cloudstack/r/network.html.markdown index 4feb566b9..339504f8e 100644 --- a/website/source/docs/providers/cloudstack/r/network.html.markdown +++ b/website/source/docs/providers/cloudstack/r/network.html.markdown @@ -49,6 +49,8 @@ The following arguments are supported: * `zone` - (Required) The name or ID of the zone where this disk volume will be available. Changing this forces a new resource to be created. +* `tags` - (Optional) A mapping of tags to assign to the resource. + ## Attributes Reference The following attributes are exported: