github.com/terramate-io/tf@v0.0.0-20230830114523-fce866b4dfcd/states/statemgr/statemgr_fake.go (about) 1 // Copyright (c) HashiCorp, Inc. 2 // SPDX-License-Identifier: MPL-2.0 3 4 package statemgr 5 6 import ( 7 "errors" 8 "sync" 9 10 "github.com/terramate-io/tf/states" 11 "github.com/terramate-io/tf/terraform" 12 ) 13 14 // NewFullFake returns a full state manager that really only supports transient 15 // snapshots. This is primarily intended for testing and is not suitable for 16 // general use. 17 // 18 // The persistent part of the interface is stubbed out as an in-memory store, 19 // and so its snapshots are effectively also transient. 20 // 21 // The given Transient implementation is used to implement the transient 22 // portion of the interface. If nil is given, NewTransientInMemory is 23 // automatically called to create an in-memory transient manager with no 24 // initial transient snapshot. 25 // 26 // If the given initial state is non-nil then a copy of it will be used as 27 // the initial persistent snapshot. 28 // 29 // The Locker portion of the returned manager uses a local mutex to simulate 30 // mutually-exclusive access to the fake persistent portion of the object. 31 func NewFullFake(t Transient, initial *states.State) Full { 32 if t == nil { 33 t = NewTransientInMemory(nil) 34 } 35 36 // The "persistent" part of our manager is actually just another in-memory 37 // transient used to fake a secondary storage layer. 38 fakeP := NewTransientInMemory(initial.DeepCopy()) 39 40 return &fakeFull{ 41 t: t, 42 fakeP: fakeP, 43 } 44 } 45 46 type fakeFull struct { 47 t Transient 48 fakeP Transient 49 50 lockLock sync.Mutex 51 locked bool 52 } 53 54 var _ Full = (*fakeFull)(nil) 55 56 func (m *fakeFull) State() *states.State { 57 return m.t.State() 58 } 59 60 func (m *fakeFull) WriteState(s *states.State) error { 61 return m.t.WriteState(s) 62 } 63 64 func (m *fakeFull) RefreshState() error { 65 return m.t.WriteState(m.fakeP.State()) 66 } 67 68 func (m *fakeFull) PersistState(schemas *terraform.Schemas) error { 69 return m.fakeP.WriteState(m.t.State()) 70 } 71 72 func (m *fakeFull) GetRootOutputValues() (map[string]*states.OutputValue, error) { 73 return m.State().RootModule().OutputValues, nil 74 } 75 76 func (m *fakeFull) Lock(info *LockInfo) (string, error) { 77 m.lockLock.Lock() 78 defer m.lockLock.Unlock() 79 80 if m.locked { 81 return "", &LockError{ 82 Err: errors.New("fake state manager is locked"), 83 Info: info, 84 } 85 } 86 87 m.locked = true 88 return "placeholder", nil 89 } 90 91 func (m *fakeFull) Unlock(id string) error { 92 m.lockLock.Lock() 93 defer m.lockLock.Unlock() 94 95 if !m.locked { 96 return errors.New("fake state manager is not locked") 97 } 98 if id != "placeholder" { 99 return errors.New("wrong lock id for fake state manager") 100 } 101 102 m.locked = false 103 return nil 104 } 105 106 // NewUnlockErrorFull returns a state manager that is useful for testing errors 107 // (mostly Unlock errors) when used with the clistate.Locker interface. Lock() 108 // does not return an error because clistate.Locker Lock()s the state at the 109 // start of Unlock(), so Lock() must succeeded for Unlock() to get called. 110 func NewUnlockErrorFull(t Transient, initial *states.State) Full { 111 return &fakeErrorFull{} 112 } 113 114 type fakeErrorFull struct{} 115 116 var _ Full = (*fakeErrorFull)(nil) 117 118 func (m *fakeErrorFull) State() *states.State { 119 return nil 120 } 121 122 func (m *fakeErrorFull) GetRootOutputValues() (map[string]*states.OutputValue, error) { 123 return nil, errors.New("fake state manager error") 124 } 125 126 func (m *fakeErrorFull) WriteState(s *states.State) error { 127 return errors.New("fake state manager error") 128 } 129 130 func (m *fakeErrorFull) RefreshState() error { 131 return errors.New("fake state manager error") 132 } 133 134 func (m *fakeErrorFull) PersistState(schemas *terraform.Schemas) error { 135 return errors.New("fake state manager error") 136 } 137 138 func (m *fakeErrorFull) Lock(info *LockInfo) (string, error) { 139 return "placeholder", nil 140 } 141 142 func (m *fakeErrorFull) Unlock(id string) error { 143 return errors.New("fake state manager error") 144 }