terraform-provider-greenhost/digitalocean/tags.go

136 lines
3.1 KiB
Go

package digitalocean
import (
"context"
"fmt"
"log"
"regexp"
"github.com/digitalocean/godo"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)
var tagNameRe = regexp.MustCompile("^[a-zA-Z0-9:\\-_]{1,255}$")
func tagsSchema() *schema.Schema {
return &schema.Schema{
Type: schema.TypeSet,
Optional: true,
Elem: &schema.Schema{
Type: schema.TypeString,
ValidateFunc: validateTag,
},
Set: HashStringIgnoreCase,
}
}
func tagsDataSourceSchema() *schema.Schema {
return &schema.Schema{
Type: schema.TypeSet,
Computed: true,
Elem: &schema.Schema{Type: schema.TypeString},
}
}
func validateTag(value interface{}, key string) ([]string, []error) {
if !tagNameRe.MatchString(value.(string)) {
return nil, []error{fmt.Errorf("tags may contain lowercase letters, numbers, colons, dashes, and underscores; there is a limit of 255 characters per tag")}
}
return nil, nil
}
// setTags is a helper to set the tags for a resource. It expects the
// tags field to be named "tags"
func setTags(conn *godo.Client, d *schema.ResourceData, resourceType godo.ResourceType) error {
oraw, nraw := d.GetChange("tags")
remove, create := diffTags(tagsFromSchema(oraw), tagsFromSchema(nraw))
log.Printf("[DEBUG] Removing tags: %#v from %s", remove, d.Id())
for _, tag := range remove {
_, err := conn.Tags.UntagResources(context.Background(), tag, &godo.UntagResourcesRequest{
Resources: []godo.Resource{
{
ID: d.Id(),
Type: resourceType,
},
},
})
if err != nil {
return err
}
}
log.Printf("[DEBUG] Creating tags: %s for %s", create, d.Id())
for _, tag := range create {
createdTag, _, err := conn.Tags.Create(context.Background(), &godo.TagCreateRequest{
Name: tag,
})
if err != nil {
return err
}
_, err = conn.Tags.TagResources(context.Background(), createdTag.Name, &godo.TagResourcesRequest{
Resources: []godo.Resource{
{
ID: d.Id(),
Type: resourceType,
},
},
})
if err != nil {
return err
}
}
return nil
}
// tagsFromSchema takes the raw schema tags and returns them as a
// properly asserted map[string]string
func tagsFromSchema(raw interface{}) map[string]string {
result := make(map[string]string)
for _, t := range raw.(*schema.Set).List() {
result[t.(string)] = t.(string)
}
return result
}
// diffTags takes the old and the new tag sets and returns the difference of
// both. The remaining tags are those that need to be removed and created
func diffTags(oldTags, newTags map[string]string) (map[string]string, map[string]string) {
for k := range oldTags {
_, ok := newTags[k]
if ok {
delete(newTags, k)
delete(oldTags, k)
}
}
return oldTags, newTags
}
func expandTags(tags []interface{}) []string {
expandedTags := make([]string, len(tags))
for i, v := range tags {
expandedTags[i] = v.(string)
}
return expandedTags
}
func flattenTags(tags []string) *schema.Set {
if tags == nil {
return nil
}
flattenedTags := schema.NewSet(HashStringIgnoreCase, []interface{}{})
for _, v := range tags {
flattenedTags.Add(v)
}
return flattenedTags
}