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