github.com/terramate-io/tf@v0.0.0-20230830114523-fce866b4dfcd/states/state_equal.go (about) 1 // Copyright (c) HashiCorp, Inc. 2 // SPDX-License-Identifier: MPL-2.0 3 4 package states 5 6 import ( 7 "reflect" 8 9 "github.com/terramate-io/tf/addrs" 10 ) 11 12 // Equal returns true if the receiver is functionally equivalent to other, 13 // including any ephemeral portions of the state that would not be included 14 // if the state were saved to files. 15 // 16 // To test only the persistent portions of two states for equality, instead 17 // use statefile.StatesMarshalEqual. 18 func (s *State) Equal(other *State) bool { 19 // For the moment this is sufficient, but we may need to do something 20 // more elaborate in future if we have any portions of state that require 21 // more sophisticated comparisons. 22 return reflect.DeepEqual(s, other) 23 } 24 25 // ManagedResourcesEqual returns true if all of the managed resources tracked 26 // in the reciever are functionally equivalent to the same tracked in the 27 // other given state. 28 // 29 // This is a more constrained version of Equal that disregards other 30 // differences, including but not limited to changes to data resources and 31 // changes to output values. 32 func (s *State) ManagedResourcesEqual(other *State) bool { 33 // First, some accommodations for situations where one of the objects is 34 // nil, for robustness since we sometimes use a nil state to represent 35 // a prior state being entirely absent. 36 if s == nil && other == nil { 37 return true 38 } 39 if s == nil { 40 return !other.HasManagedResourceInstanceObjects() 41 } 42 if other == nil { 43 return !s.HasManagedResourceInstanceObjects() 44 } 45 46 // If we get here then both states are non-nil. 47 48 // sameManagedResources tests that its second argument has all the 49 // resources that the first one does, so we'll call it twice with the 50 // arguments inverted to ensure that we'll also catch situations where 51 // the second has resources that the first does not. 52 return sameManagedResources(s, other) && sameManagedResources(other, s) 53 } 54 55 func sameManagedResources(s1, s2 *State) bool { 56 for _, ms := range s1.Modules { 57 for _, rs := range ms.Resources { 58 addr := rs.Addr 59 if addr.Resource.Mode != addrs.ManagedResourceMode { 60 continue 61 } 62 otherRS := s2.Resource(addr) 63 if !reflect.DeepEqual(rs, otherRS) { 64 return false 65 } 66 } 67 } 68 69 return true 70 71 }