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  }