github.com/xsb/terraform@v0.6.13-0.20160314145438-fe415c2f09d7/helper/schema/serialize.go (about) 1 package schema 2 3 import ( 4 "bytes" 5 "sort" 6 "strconv" 7 ) 8 9 func SerializeValueForHash(buf *bytes.Buffer, val interface{}, schema *Schema) { 10 if val == nil { 11 buf.WriteRune(';') 12 return 13 } 14 15 switch schema.Type { 16 case TypeBool: 17 if val.(bool) { 18 buf.WriteRune('1') 19 } else { 20 buf.WriteRune('0') 21 } 22 case TypeInt: 23 buf.WriteString(strconv.Itoa(val.(int))) 24 case TypeFloat: 25 buf.WriteString(strconv.FormatFloat(val.(float64), 'g', -1, 64)) 26 case TypeString: 27 buf.WriteString(val.(string)) 28 case TypeList: 29 buf.WriteRune('(') 30 l := val.([]interface{}) 31 for _, innerVal := range l { 32 serializeCollectionMemberForHash(buf, innerVal, schema.Elem) 33 } 34 buf.WriteRune(')') 35 case TypeMap: 36 m := val.(map[string]interface{}) 37 var keys []string 38 for k := range m { 39 keys = append(keys, k) 40 } 41 sort.Strings(keys) 42 buf.WriteRune('[') 43 for _, k := range keys { 44 innerVal := m[k] 45 buf.WriteString(k) 46 buf.WriteRune(':') 47 serializeCollectionMemberForHash(buf, innerVal, schema.Elem) 48 } 49 buf.WriteRune(']') 50 case TypeSet: 51 buf.WriteRune('{') 52 s := val.(*Set) 53 for _, innerVal := range s.List() { 54 serializeCollectionMemberForHash(buf, innerVal, schema.Elem) 55 } 56 buf.WriteRune('}') 57 default: 58 panic("unknown schema type to serialize") 59 } 60 buf.WriteRune(';') 61 } 62 63 // SerializeValueForHash appends a serialization of the given resource config 64 // to the given buffer, guaranteeing deterministic results given the same value 65 // and schema. 66 // 67 // Its primary purpose is as input into a hashing function in order 68 // to hash complex substructures when used in sets, and so the serialization 69 // is not reversible. 70 func SerializeResourceForHash(buf *bytes.Buffer, val interface{}, resource *Resource) { 71 sm := resource.Schema 72 m := val.(map[string]interface{}) 73 var keys []string 74 for k := range sm { 75 keys = append(keys, k) 76 } 77 sort.Strings(keys) 78 for _, k := range keys { 79 innerSchema := sm[k] 80 // Skip attributes that are not user-provided. Computed attributes 81 // do not contribute to the hash since their ultimate value cannot 82 // be known at plan/diff time. 83 if !(innerSchema.Required || innerSchema.Optional) { 84 continue 85 } 86 87 buf.WriteString(k) 88 buf.WriteRune(':') 89 innerVal := m[k] 90 SerializeValueForHash(buf, innerVal, innerSchema) 91 } 92 } 93 94 func serializeCollectionMemberForHash(buf *bytes.Buffer, val interface{}, elem interface{}) { 95 switch tElem := elem.(type) { 96 case *Schema: 97 SerializeValueForHash(buf, val, tElem) 98 case *Resource: 99 buf.WriteRune('<') 100 SerializeResourceForHash(buf, val, tElem) 101 buf.WriteString(">;") 102 default: 103 panic("invalid element type") 104 } 105 }