From 124b80398ec4a8921bbdc33d8208f0797d9359e6 Mon Sep 17 00:00:00 2001 From: James Bardin Date: Fri, 30 Jun 2017 18:29:42 -0400 Subject: [PATCH] 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. --- terraform/state.go | 15 +++++++++++++- terraform/state_test.go | 44 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+), 1 deletion(-) diff --git a/terraform/state.go b/terraform/state.go index 074b68245..19df3c996 100644 --- a/terraform/state.go +++ b/terraform/state.go @@ -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 } } diff --git a/terraform/state_test.go b/terraform/state_test.go index 5578f89c9..797274189 100644 --- a/terraform/state_test.go +++ b/terraform/state_test.go @@ -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 {