make sure marshaled Meta fields are still equal

When the InstanceState.Meta fields are marshaled, numeric values may
change types. The timeout system currently inserts integer values, which
will be unmarshal as float64s.

To ensure that a state which has round-tripped through json is equal to
itself, compare the json representation of the Meta values.
This commit is contained in:
James Bardin 2017-06-30 18:29:42 -04:00
parent e6ddd62583
commit 124b80398e
2 changed files with 58 additions and 1 deletions

View File

@ -1663,7 +1663,20 @@ func (s *InstanceState) Equal(other *InstanceState) bool {
// We only do the deep check if both are non-nil. If one is nil
// we treat it as equal since their lengths are both zero (check
// above).
if !reflect.DeepEqual(s.Meta, other.Meta) {
//
// Since this can contain numeric values that may change types during
// serialization, let's compare the serialized values.
sMeta, err := json.Marshal(s.Meta)
if err != nil {
// marshaling primitives shouldn't ever error out
panic(err)
}
otherMeta, err := json.Marshal(other.Meta)
if err != nil {
panic(err)
}
if !bytes.Equal(sMeta, otherMeta) {
return false
}
}

View File

@ -467,6 +467,50 @@ func TestStateEqual(t *testing.T) {
},
},
},
// Meta with complex types that have been altered during serialization
{
"same meta with complex types that have been json-ified",
true,
&State{
Modules: []*ModuleState{
&ModuleState{
Path: rootModulePath,
Resources: map[string]*ResourceState{
"test_instance.foo": &ResourceState{
Primary: &InstanceState{
Meta: map[string]interface{}{
"timeouts": map[string]interface{}{
"create": int(42),
"read": "27",
},
},
},
},
},
},
},
},
&State{
Modules: []*ModuleState{
&ModuleState{
Path: rootModulePath,
Resources: map[string]*ResourceState{
"test_instance.foo": &ResourceState{
Primary: &InstanceState{
Meta: map[string]interface{}{
"timeouts": map[string]interface{}{
"create": float64(42),
"read": "27",
},
},
},
},
},
},
},
},
},
}
for i, tc := range cases {