Skip to content

Commit d60365a

Browse files
committed
core: Correctly ensure that State() is a copy
The previous mechanism for testing state threw away the mutation made on the state by calling State() twice - this commit corrects the test to match the comment. In addition, we replace the custom copying logic with the copystructure library to simplify the code.
1 parent b190aa0 commit d60365a

2 files changed

Lines changed: 24 additions & 69 deletions

File tree

state/testing.go

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -118,9 +118,11 @@ func TestState(t *testing.T, s interface{}) {
118118
t.Fatalf("bad: expected %d, got %d", serial, reader.State().Serial)
119119
}
120120

121-
// Check that State() returns a copy
122-
reader.State().Serial++
123-
if reflect.DeepEqual(reader.State(), current) {
121+
// Check that State() returns a copy by modifying the copy and comparing
122+
// to the current state.
123+
stateCopy := reader.State()
124+
stateCopy.Serial++
125+
if reflect.DeepEqual(stateCopy, current) {
124126
t.Fatal("State() should return a copy")
125127
}
126128
}

terraform/state.go

Lines changed: 19 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -458,23 +458,12 @@ func (s *State) SameLineage(other *State) bool {
458458
// DeepCopy performs a deep copy of the state structure and returns
459459
// a new structure.
460460
func (s *State) DeepCopy() *State {
461-
if s == nil {
462-
return nil
463-
}
464-
n := &State{
465-
Version: s.Version,
466-
Lineage: s.Lineage,
467-
TFVersion: s.TFVersion,
468-
Serial: s.Serial,
469-
Modules: make([]*ModuleState, 0, len(s.Modules)),
470-
}
471-
for _, mod := range s.Modules {
472-
n.Modules = append(n.Modules, mod.deepcopy())
473-
}
474-
if s.Remote != nil {
475-
n.Remote = s.Remote.deepcopy()
461+
copy, err := copystructure.Copy(s)
462+
if err != nil {
463+
panic(err)
476464
}
477-
return n
465+
466+
return copy.(*State)
478467
}
479468

480469
// IncrementSerialMaybe increments the serial number of this state
@@ -1187,28 +1176,12 @@ func (r *ResourceState) init() {
11871176
}
11881177

11891178
func (r *ResourceState) deepcopy() *ResourceState {
1190-
if r == nil {
1191-
return nil
1192-
}
1193-
1194-
n := &ResourceState{
1195-
Type: r.Type,
1196-
Dependencies: nil,
1197-
Primary: r.Primary.DeepCopy(),
1198-
Provider: r.Provider,
1199-
}
1200-
if r.Dependencies != nil {
1201-
n.Dependencies = make([]string, len(r.Dependencies))
1202-
copy(n.Dependencies, r.Dependencies)
1203-
}
1204-
if r.Deposed != nil {
1205-
n.Deposed = make([]*InstanceState, 0, len(r.Deposed))
1206-
for _, inst := range r.Deposed {
1207-
n.Deposed = append(n.Deposed, inst.DeepCopy())
1208-
}
1179+
copy, err := copystructure.Copy(r)
1180+
if err != nil {
1181+
panic(err)
12091182
}
12101183

1211-
return n
1184+
return copy.(*ResourceState)
12121185
}
12131186

12141187
// prune is used to remove any instances that are no longer required
@@ -1278,27 +1251,12 @@ func (i *InstanceState) init() {
12781251
}
12791252

12801253
func (i *InstanceState) DeepCopy() *InstanceState {
1281-
if i == nil {
1282-
return nil
1283-
}
1284-
n := &InstanceState{
1285-
ID: i.ID,
1286-
Ephemeral: *i.Ephemeral.DeepCopy(),
1287-
Tainted: i.Tainted,
1288-
}
1289-
if i.Attributes != nil {
1290-
n.Attributes = make(map[string]string, len(i.Attributes))
1291-
for k, v := range i.Attributes {
1292-
n.Attributes[k] = v
1293-
}
1294-
}
1295-
if i.Meta != nil {
1296-
n.Meta = make(map[string]string, len(i.Meta))
1297-
for k, v := range i.Meta {
1298-
n.Meta[k] = v
1299-
}
1254+
copy, err := copystructure.Copy(i)
1255+
if err != nil {
1256+
panic(err)
13001257
}
1301-
return n
1258+
1259+
return copy.(*InstanceState)
13021260
}
13031261

13041262
func (s *InstanceState) Empty() bool {
@@ -1446,17 +1404,12 @@ func (e *EphemeralState) init() {
14461404
}
14471405

14481406
func (e *EphemeralState) DeepCopy() *EphemeralState {
1449-
if e == nil {
1450-
return nil
1451-
}
1452-
n := &EphemeralState{}
1453-
if e.ConnInfo != nil {
1454-
n.ConnInfo = make(map[string]string, len(e.ConnInfo))
1455-
for k, v := range e.ConnInfo {
1456-
n.ConnInfo[k] = v
1457-
}
1407+
copy, err := copystructure.Copy(e)
1408+
if err != nil {
1409+
panic(err)
14581410
}
1459-
return n
1411+
1412+
return copy.(*EphemeralState)
14601413
}
14611414

14621415
type jsonStateVersionIdentifier struct {

0 commit comments

Comments
 (0)