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  }