github.com/opentofu/opentofu@v1.7.1/internal/states/statemgr/statemgr_fake.go (about)

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