2018-06-09 01:18:30 +02:00
|
|
|
package statemgr
|
|
|
|
|
|
|
|
import (
|
|
|
|
"errors"
|
|
|
|
"sync"
|
|
|
|
|
2021-05-17 21:43:35 +02:00
|
|
|
"github.com/hashicorp/terraform/internal/states"
|
2018-06-09 01:18:30 +02:00
|
|
|
)
|
|
|
|
|
|
|
|
// NewFullFake returns a full state manager that really only supports transient
|
|
|
|
// snapshots. This is primarily intended for testing and is not suitable for
|
|
|
|
// general use.
|
|
|
|
//
|
|
|
|
// The persistent part of the interface is stubbed out as an in-memory store,
|
|
|
|
// and so its snapshots are effectively also transient.
|
|
|
|
//
|
|
|
|
// The given Transient implementation is used to implement the transient
|
|
|
|
// portion of the interface. If nil is given, NewTransientInMemory is
|
|
|
|
// automatically called to create an in-memory transient manager with no
|
|
|
|
// initial transient snapshot.
|
|
|
|
//
|
|
|
|
// If the given initial state is non-nil then a copy of it will be used as
|
|
|
|
// the initial persistent snapshot.
|
|
|
|
//
|
|
|
|
// The Locker portion of the returned manager uses a local mutex to simulate
|
|
|
|
// mutually-exclusive access to the fake persistent portion of the object.
|
|
|
|
func NewFullFake(t Transient, initial *states.State) Full {
|
|
|
|
if t == nil {
|
|
|
|
t = NewTransientInMemory(nil)
|
|
|
|
}
|
|
|
|
|
|
|
|
// The "persistent" part of our manager is actually just another in-memory
|
|
|
|
// transient used to fake a secondary storage layer.
|
|
|
|
fakeP := NewTransientInMemory(initial.DeepCopy())
|
|
|
|
|
|
|
|
return &fakeFull{
|
|
|
|
t: t,
|
|
|
|
fakeP: fakeP,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
type fakeFull struct {
|
|
|
|
t Transient
|
|
|
|
fakeP Transient
|
|
|
|
|
|
|
|
lockLock sync.Mutex
|
|
|
|
locked bool
|
|
|
|
}
|
|
|
|
|
|
|
|
var _ Full = (*fakeFull)(nil)
|
|
|
|
|
|
|
|
func (m *fakeFull) State() *states.State {
|
|
|
|
return m.t.State()
|
|
|
|
}
|
|
|
|
|
|
|
|
func (m *fakeFull) WriteState(s *states.State) error {
|
|
|
|
return m.t.WriteState(s)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (m *fakeFull) RefreshState() error {
|
|
|
|
return m.t.WriteState(m.fakeP.State())
|
|
|
|
}
|
|
|
|
|
|
|
|
func (m *fakeFull) PersistState() error {
|
|
|
|
return m.fakeP.WriteState(m.t.State())
|
|
|
|
}
|
|
|
|
|
|
|
|
func (m *fakeFull) Lock(info *LockInfo) (string, error) {
|
|
|
|
m.lockLock.Lock()
|
|
|
|
defer m.lockLock.Unlock()
|
|
|
|
|
|
|
|
if m.locked {
|
|
|
|
return "", &LockError{
|
|
|
|
Err: errors.New("fake state manager is locked"),
|
|
|
|
Info: info,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
m.locked = true
|
|
|
|
return "placeholder", nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (m *fakeFull) Unlock(id string) error {
|
|
|
|
m.lockLock.Lock()
|
|
|
|
defer m.lockLock.Unlock()
|
|
|
|
|
|
|
|
if !m.locked {
|
|
|
|
return errors.New("fake state manager is not locked")
|
|
|
|
}
|
|
|
|
if id != "placeholder" {
|
|
|
|
return errors.New("wrong lock id for fake state manager")
|
|
|
|
}
|
|
|
|
|
|
|
|
m.locked = false
|
|
|
|
return nil
|
|
|
|
}
|
2020-08-14 20:14:51 +02:00
|
|
|
|
|
|
|
// NewUnlockErrorFull returns a state manager that is useful for testing errors
|
|
|
|
// (mostly Unlock errors) when used with the clistate.Locker interface. Lock()
|
|
|
|
// does not return an error because clistate.Locker Lock()s the state at the
|
|
|
|
// start of Unlock(), so Lock() must succeeded for Unlock() to get called.
|
|
|
|
func NewUnlockErrorFull(t Transient, initial *states.State) Full {
|
|
|
|
return &fakeErrorFull{}
|
|
|
|
}
|
|
|
|
|
|
|
|
type fakeErrorFull struct{}
|
|
|
|
|
|
|
|
var _ Full = (*fakeErrorFull)(nil)
|
|
|
|
|
|
|
|
func (m *fakeErrorFull) State() *states.State {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (m *fakeErrorFull) WriteState(s *states.State) error {
|
|
|
|
return errors.New("fake state manager error")
|
|
|
|
}
|
|
|
|
|
|
|
|
func (m *fakeErrorFull) RefreshState() error {
|
|
|
|
return errors.New("fake state manager error")
|
|
|
|
}
|
|
|
|
|
|
|
|
func (m *fakeErrorFull) PersistState() error {
|
|
|
|
return errors.New("fake state manager error")
|
|
|
|
}
|
|
|
|
|
|
|
|
func (m *fakeErrorFull) Lock(info *LockInfo) (string, error) {
|
|
|
|
return "placeholder", nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (m *fakeErrorFull) Unlock(id string) error {
|
|
|
|
return errors.New("fake state manager error")
|
|
|
|
}
|