summaryrefslogtreecommitdiff
path: root/vendor/github.com/hashicorp/terraform/helper/schema/serialize.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/hashicorp/terraform/helper/schema/serialize.go')
-rw-r--r--vendor/github.com/hashicorp/terraform/helper/schema/serialize.go122
1 files changed, 122 insertions, 0 deletions
diff --git a/vendor/github.com/hashicorp/terraform/helper/schema/serialize.go b/vendor/github.com/hashicorp/terraform/helper/schema/serialize.go
new file mode 100644
index 00000000..3eb2d007
--- /dev/null
+++ b/vendor/github.com/hashicorp/terraform/helper/schema/serialize.go
@@ -0,0 +1,122 @@
+package schema
+
+import (
+ "bytes"
+ "fmt"
+ "sort"
+ "strconv"
+)
+
+func SerializeValueForHash(buf *bytes.Buffer, val interface{}, schema *Schema) {
+ if val == nil {
+ buf.WriteRune(';')
+ return
+ }
+
+ switch schema.Type {
+ case TypeBool:
+ if val.(bool) {
+ buf.WriteRune('1')
+ } else {
+ buf.WriteRune('0')
+ }
+ case TypeInt:
+ buf.WriteString(strconv.Itoa(val.(int)))
+ case TypeFloat:
+ buf.WriteString(strconv.FormatFloat(val.(float64), 'g', -1, 64))
+ case TypeString:
+ buf.WriteString(val.(string))
+ case TypeList:
+ buf.WriteRune('(')
+ l := val.([]interface{})
+ for _, innerVal := range l {
+ serializeCollectionMemberForHash(buf, innerVal, schema.Elem)
+ }
+ buf.WriteRune(')')
+ case TypeMap:
+
+ m := val.(map[string]interface{})
+ var keys []string
+ for k := range m {
+ keys = append(keys, k)
+ }
+ sort.Strings(keys)
+ buf.WriteRune('[')
+ for _, k := range keys {
+ innerVal := m[k]
+ if innerVal == nil {
+ continue
+ }
+ buf.WriteString(k)
+ buf.WriteRune(':')
+
+ switch innerVal := innerVal.(type) {
+ case int:
+ buf.WriteString(strconv.Itoa(innerVal))
+ case float64:
+ buf.WriteString(strconv.FormatFloat(innerVal, 'g', -1, 64))
+ case string:
+ buf.WriteString(innerVal)
+ default:
+ panic(fmt.Sprintf("unknown value type in TypeMap %T", innerVal))
+ }
+
+ buf.WriteRune(';')
+ }
+ buf.WriteRune(']')
+ case TypeSet:
+ buf.WriteRune('{')
+ s := val.(*Set)
+ for _, innerVal := range s.List() {
+ serializeCollectionMemberForHash(buf, innerVal, schema.Elem)
+ }
+ buf.WriteRune('}')
+ default:
+ panic("unknown schema type to serialize")
+ }
+ buf.WriteRune(';')
+}
+
+// SerializeValueForHash appends a serialization of the given resource config
+// to the given buffer, guaranteeing deterministic results given the same value
+// and schema.
+//
+// Its primary purpose is as input into a hashing function in order
+// to hash complex substructures when used in sets, and so the serialization
+// is not reversible.
+func SerializeResourceForHash(buf *bytes.Buffer, val interface{}, resource *Resource) {
+ sm := resource.Schema
+ m := val.(map[string]interface{})
+ var keys []string
+ for k := range sm {
+ keys = append(keys, k)
+ }
+ sort.Strings(keys)
+ for _, k := range keys {
+ innerSchema := sm[k]
+ // Skip attributes that are not user-provided. Computed attributes
+ // do not contribute to the hash since their ultimate value cannot
+ // be known at plan/diff time.
+ if !(innerSchema.Required || innerSchema.Optional) {
+ continue
+ }
+
+ buf.WriteString(k)
+ buf.WriteRune(':')
+ innerVal := m[k]
+ SerializeValueForHash(buf, innerVal, innerSchema)
+ }
+}
+
+func serializeCollectionMemberForHash(buf *bytes.Buffer, val interface{}, elem interface{}) {
+ switch tElem := elem.(type) {
+ case *Schema:
+ SerializeValueForHash(buf, val, tElem)
+ case *Resource:
+ buf.WriteRune('<')
+ SerializeResourceForHash(buf, val, tElem)
+ buf.WriteString(">;")
+ default:
+ panic(fmt.Sprintf("invalid element type: %T", tElem))
+ }
+}