mirror of
https://github.com/opentffoundation/opentf.git
synced 2025-12-19 17:59:05 -05:00
wip
This commit is contained in:
@@ -365,7 +365,11 @@ func (b *Local) opWait(
|
||||
|
||||
// try to force a PersistState just in case the process is terminated
|
||||
// before we can complete.
|
||||
if err := opStateMgr.PersistState(nil); err != nil {
|
||||
// FIXME: This should use a context.WithoutCancel context derived from
|
||||
// the active request context, once we have that plumbed in here.
|
||||
// However, we want to tidy up our big multi-context mess in here
|
||||
// before adding yet another context into the mix.
|
||||
if err := opStateMgr.PersistState(context.TODO(), nil); err != nil {
|
||||
// We can't error out from here, but warn the user if there was an error.
|
||||
// If this isn't transient, we will catch it again below, and
|
||||
// attempt to save the state another way.
|
||||
|
||||
@@ -286,9 +286,10 @@ func (b *Local) opApply(
|
||||
return
|
||||
}
|
||||
|
||||
// Store the final state
|
||||
// Store the final state, ignoring any context cancellation
|
||||
stateStoreCtx := context.WithoutCancel(ctx)
|
||||
runningOp.State = applyState
|
||||
err := statemgr.WriteAndPersist(opState, applyState, schemas)
|
||||
err := statemgr.WriteAndPersist(stateStoreCtx, opState, applyState, schemas)
|
||||
if err != nil {
|
||||
// Export the state file from the state manager and assign the new
|
||||
// state. This is needed to preserve the existing serial and lineage.
|
||||
|
||||
@@ -68,7 +68,7 @@ func (b *Local) localRun(ctx context.Context, op *backend.Operation) (*backend.L
|
||||
}()
|
||||
|
||||
log.Printf("[TRACE] backend/local: reading remote state for workspace %q", op.Workspace)
|
||||
if err := s.RefreshState(); err != nil {
|
||||
if err := s.RefreshState(ctx); err != nil {
|
||||
diags = diags.Append(fmt.Errorf("error loading state: %w", err))
|
||||
return nil, nil, nil, diags
|
||||
}
|
||||
|
||||
@@ -142,7 +142,7 @@ func TestLocalRun_stalePlan(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
if err := sm.RefreshState(); err != nil {
|
||||
if err := sm.RefreshState(t.Context()); err != nil {
|
||||
t.Fatalf("unexpected error refreshing state: %s", err)
|
||||
}
|
||||
|
||||
@@ -242,7 +242,7 @@ type stateStorageThatFailsRefresh struct {
|
||||
|
||||
var _ statemgr.Full = (*stateStorageThatFailsRefresh)(nil)
|
||||
|
||||
func (s *stateStorageThatFailsRefresh) Lock(info *statemgr.LockInfo) (string, error) {
|
||||
func (s *stateStorageThatFailsRefresh) Lock(_ context.Context, info *statemgr.LockInfo) (string, error) {
|
||||
if s.locked {
|
||||
return "", fmt.Errorf("already locked")
|
||||
}
|
||||
@@ -250,7 +250,7 @@ func (s *stateStorageThatFailsRefresh) Lock(info *statemgr.LockInfo) (string, er
|
||||
return "locked", nil
|
||||
}
|
||||
|
||||
func (s *stateStorageThatFailsRefresh) Unlock(id string) error {
|
||||
func (s *stateStorageThatFailsRefresh) Unlock(_ context.Context, id string) error {
|
||||
if !s.locked {
|
||||
return fmt.Errorf("not locked")
|
||||
}
|
||||
@@ -262,7 +262,7 @@ func (s *stateStorageThatFailsRefresh) State() *states.State {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *stateStorageThatFailsRefresh) GetRootOutputValues() (map[string]*states.OutputValue, error) {
|
||||
func (s *stateStorageThatFailsRefresh) GetRootOutputValues(_ context.Context) (map[string]*states.OutputValue, error) {
|
||||
return nil, fmt.Errorf("unimplemented")
|
||||
}
|
||||
|
||||
@@ -270,10 +270,10 @@ func (s *stateStorageThatFailsRefresh) WriteState(*states.State) error {
|
||||
return fmt.Errorf("unimplemented")
|
||||
}
|
||||
|
||||
func (s *stateStorageThatFailsRefresh) RefreshState() error {
|
||||
func (s *stateStorageThatFailsRefresh) RefreshState(_ context.Context) error {
|
||||
return fmt.Errorf("intentionally failing for testing purposes")
|
||||
}
|
||||
|
||||
func (s *stateStorageThatFailsRefresh) PersistState(schemas *tofu.Schemas) error {
|
||||
func (s *stateStorageThatFailsRefresh) PersistState(_ context.Context, schemas *tofu.Schemas) error {
|
||||
return fmt.Errorf("unimplemented")
|
||||
}
|
||||
|
||||
@@ -119,7 +119,7 @@ func (b *Local) opRefresh(
|
||||
return
|
||||
}
|
||||
|
||||
err := statemgr.WriteAndPersist(opState, newState, schemas)
|
||||
err := statemgr.WriteAndPersist(context.WithoutCancel(ctx), opState, newState, schemas)
|
||||
if err != nil {
|
||||
diags = diags.Append(fmt.Errorf("failed to write state: %w", err))
|
||||
op.ReportResult(runningOp, diags)
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
package local
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log"
|
||||
"sync"
|
||||
"time"
|
||||
@@ -81,7 +82,7 @@ func (h *StateHook) PostStateUpdate(new *states.State) (tofu.HookAction, error)
|
||||
}
|
||||
if mgrPersist, ok := h.StateMgr.(statemgr.Persister); ok && h.PersistInterval != 0 && h.Schemas != nil {
|
||||
if h.shouldPersist() {
|
||||
err := mgrPersist.PersistState(h.Schemas)
|
||||
err := mgrPersist.PersistState(context.TODO(), h.Schemas)
|
||||
if err != nil {
|
||||
return tofu.HookActionHalt, err
|
||||
}
|
||||
@@ -115,7 +116,7 @@ func (h *StateHook) Stopping() {
|
||||
h.intermediatePersist.ForcePersist = true
|
||||
|
||||
if h.shouldPersist() {
|
||||
err := mgrPersist.PersistState(h.Schemas)
|
||||
err := mgrPersist.PersistState(context.TODO(), h.Schemas)
|
||||
if err != nil {
|
||||
// This hook can't affect OpenTofu Core's ongoing behavior,
|
||||
// but it's a best effort thing anyway, so we'll just emit a
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
package local
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"testing"
|
||||
"time"
|
||||
@@ -281,7 +282,7 @@ func (sm *testPersistentState) WriteState(state *states.State) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (sm *testPersistentState) PersistState(schemas *tofu.Schemas) error {
|
||||
func (sm *testPersistentState) PersistState(_ context.Context, schemas *tofu.Schemas) error {
|
||||
if schemas == nil {
|
||||
return fmt.Errorf("no schemas")
|
||||
}
|
||||
@@ -307,7 +308,7 @@ func (sm *testPersistentStateThatRefusesToPersist) WriteState(state *states.Stat
|
||||
return nil
|
||||
}
|
||||
|
||||
func (sm *testPersistentStateThatRefusesToPersist) PersistState(schemas *tofu.Schemas) error {
|
||||
func (sm *testPersistentStateThatRefusesToPersist) PersistState(_ context.Context, schemas *tofu.Schemas) error {
|
||||
if schemas == nil {
|
||||
return fmt.Errorf("no schemas")
|
||||
}
|
||||
|
||||
@@ -184,7 +184,7 @@ func (b *TestLocalNoDefaultState) StateMgr(ctx context.Context, name string) (st
|
||||
func testStateFile(t *testing.T, path string, s *states.State) {
|
||||
t.Helper()
|
||||
|
||||
if err := statemgr.WriteAndPersist(statemgr.NewFilesystem(path, encryption.StateEncryptionDisabled()), s, nil); err != nil {
|
||||
if err := statemgr.WriteAndPersist(t.Context(), statemgr.NewFilesystem(path, encryption.StateEncryptionDisabled()), s, nil); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
@@ -211,7 +211,7 @@ func mustResourceInstanceAddr(s string) addrs.AbsResourceInstance {
|
||||
func assertBackendStateUnlocked(t *testing.T, b *Local) bool {
|
||||
t.Helper()
|
||||
stateMgr, _ := b.StateMgr(t.Context(), backend.DefaultStateName)
|
||||
if _, err := stateMgr.Lock(statemgr.NewLockInfo()); err != nil {
|
||||
if _, err := stateMgr.Lock(t.Context(), statemgr.NewLockInfo()); err != nil {
|
||||
t.Errorf("state is already locked: %s", err.Error())
|
||||
// lock was obtained
|
||||
return false
|
||||
@@ -226,7 +226,7 @@ func assertBackendStateUnlocked(t *testing.T, b *Local) bool {
|
||||
func assertBackendStateLocked(t *testing.T, b *Local) bool {
|
||||
t.Helper()
|
||||
stateMgr, _ := b.StateMgr(t.Context(), backend.DefaultStateName)
|
||||
if _, err := stateMgr.Lock(statemgr.NewLockInfo()); err != nil {
|
||||
if _, err := stateMgr.Lock(t.Context(), statemgr.NewLockInfo()); err != nil {
|
||||
// lock was not obtained
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -92,7 +92,7 @@ func (b *Backend) StateMgr(ctx context.Context, name string) (statemgr.Full, err
|
||||
stateMgr := remote.NewState(client, b.encryption)
|
||||
|
||||
// Grab the value
|
||||
if err := stateMgr.RefreshState(); err != nil {
|
||||
if err := stateMgr.RefreshState(ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
//if this isn't the default state name, we need to create the object so
|
||||
@@ -101,21 +101,21 @@ func (b *Backend) StateMgr(ctx context.Context, name string) (statemgr.Full, err
|
||||
// take a lock on this state while we write it
|
||||
lockInfo := statemgr.NewLockInfo()
|
||||
lockInfo.Operation = "init"
|
||||
lockId, err := client.Lock(lockInfo)
|
||||
lockId, err := client.Lock(ctx, lockInfo)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to lock azure state: %w", err)
|
||||
}
|
||||
|
||||
// Local helper function so we can call it multiple places
|
||||
lockUnlock := func(parent error) error {
|
||||
if err := stateMgr.Unlock(lockId); err != nil {
|
||||
if err := stateMgr.Unlock(ctx, lockId); err != nil {
|
||||
return fmt.Errorf(strings.TrimSpace(errStateUnlock), lockId, err)
|
||||
}
|
||||
return parent
|
||||
}
|
||||
|
||||
// Grab the value
|
||||
if err := stateMgr.RefreshState(); err != nil {
|
||||
if err := stateMgr.RefreshState(ctx); err != nil {
|
||||
err = lockUnlock(err)
|
||||
return nil, err
|
||||
}
|
||||
@@ -127,7 +127,7 @@ func (b *Backend) StateMgr(ctx context.Context, name string) (statemgr.Full, err
|
||||
err = lockUnlock(err)
|
||||
return nil, err
|
||||
}
|
||||
if err := stateMgr.PersistState(nil); err != nil {
|
||||
if err := stateMgr.PersistState(ctx, nil); err != nil {
|
||||
err = lockUnlock(err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -102,7 +102,7 @@ func (c *RemoteClient) Delete() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *RemoteClient) Lock(info *statemgr.LockInfo) (string, error) {
|
||||
func (c *RemoteClient) Lock(ctx context.Context, info *statemgr.LockInfo) (string, error) {
|
||||
stateName := fmt.Sprintf("%s/%s", c.containerName, c.keyName)
|
||||
info.Path = stateName
|
||||
|
||||
@@ -131,7 +131,6 @@ func (c *RemoteClient) Lock(info *statemgr.LockInfo) (string, error) {
|
||||
ProposedLeaseID: &info.ID,
|
||||
LeaseDuration: -1,
|
||||
}
|
||||
ctx := context.TODO()
|
||||
|
||||
// obtain properties to see if the blob lease is already in use. If the blob doesn't exist, create it
|
||||
properties, err := c.getBlobProperties()
|
||||
@@ -221,7 +220,7 @@ func (c *RemoteClient) writeLockInfo(info *statemgr.LockInfo) error {
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *RemoteClient) Unlock(id string) error {
|
||||
func (c *RemoteClient) Unlock(ctx context.Context, id string) error {
|
||||
lockErr := &statemgr.LockError{}
|
||||
|
||||
lockInfo, err := c.getLockInfo()
|
||||
@@ -242,7 +241,7 @@ func (c *RemoteClient) Unlock(id string) error {
|
||||
return lockErr
|
||||
}
|
||||
|
||||
ctx := context.TODO()
|
||||
ctx = context.WithoutCancel(ctx) // try to release even if we're cancelled
|
||||
_, err = c.giovanniBlobClient.ReleaseLease(ctx, c.accountName, c.containerName, c.keyName, id)
|
||||
if err != nil {
|
||||
lockErr.Err = err
|
||||
|
||||
@@ -69,7 +69,7 @@ func (b *Backend) DeleteWorkspace(_ context.Context, name string, _ bool) error
|
||||
return err
|
||||
}
|
||||
|
||||
func (b *Backend) StateMgr(_ context.Context, name string) (statemgr.Full, error) {
|
||||
func (b *Backend) StateMgr(ctx context.Context, name string) (statemgr.Full, error) {
|
||||
// Determine the path of the data
|
||||
path := b.path(name)
|
||||
|
||||
@@ -101,14 +101,14 @@ func (b *Backend) StateMgr(_ context.Context, name string) (statemgr.Full, error
|
||||
// so States() knows it exists.
|
||||
lockInfo := statemgr.NewLockInfo()
|
||||
lockInfo.Operation = "init"
|
||||
lockId, err := stateMgr.Lock(lockInfo)
|
||||
lockId, err := stateMgr.Lock(ctx, lockInfo)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to lock state in Consul: %w", err)
|
||||
}
|
||||
|
||||
// Local helper function so we can call it multiple places
|
||||
lockUnlock := func(parent error) error {
|
||||
if err := stateMgr.Unlock(lockId); err != nil {
|
||||
if err := stateMgr.Unlock(ctx, lockId); err != nil {
|
||||
return fmt.Errorf(strings.TrimSpace(errStateUnlock), lockId, err)
|
||||
}
|
||||
|
||||
@@ -116,7 +116,7 @@ func (b *Backend) StateMgr(_ context.Context, name string) (statemgr.Full, error
|
||||
}
|
||||
|
||||
// Grab the value
|
||||
if err := stateMgr.RefreshState(); err != nil {
|
||||
if err := stateMgr.RefreshState(ctx); err != nil {
|
||||
err = lockUnlock(err)
|
||||
return nil, err
|
||||
}
|
||||
@@ -127,7 +127,7 @@ func (b *Backend) StateMgr(_ context.Context, name string) (statemgr.Full, error
|
||||
err = lockUnlock(err)
|
||||
return nil, err
|
||||
}
|
||||
if err := stateMgr.PersistState(nil); err != nil {
|
||||
if err := stateMgr.PersistState(context.WithoutCancel(ctx), nil); err != nil {
|
||||
err = lockUnlock(err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -361,7 +361,7 @@ func (c *RemoteClient) getLockInfo() (*statemgr.LockInfo, error) {
|
||||
return li, nil
|
||||
}
|
||||
|
||||
func (c *RemoteClient) Lock(info *statemgr.LockInfo) (string, error) {
|
||||
func (c *RemoteClient) Lock(ctx context.Context, info *statemgr.LockInfo) (string, error) {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
|
||||
@@ -385,12 +385,12 @@ func (c *RemoteClient) Lock(info *statemgr.LockInfo) (string, error) {
|
||||
}
|
||||
}
|
||||
|
||||
return c.lock()
|
||||
return c.lock(ctx)
|
||||
}
|
||||
|
||||
// the lock implementation.
|
||||
// Only to be called while holding Client.mu
|
||||
func (c *RemoteClient) lock() (string, error) {
|
||||
func (c *RemoteClient) lock(ctx context.Context) (string, error) {
|
||||
// We create a new session here, so it can be canceled when the lock is
|
||||
// lost or unlocked.
|
||||
lockSession, err := c.createSession()
|
||||
@@ -457,7 +457,7 @@ func (c *RemoteClient) lock() (string, error) {
|
||||
|
||||
err = c.putLockInfo(c.info)
|
||||
if err != nil {
|
||||
if unlockErr := c.unlock(c.info.ID); unlockErr != nil {
|
||||
if unlockErr := c.unlock(ctx, c.info.ID); unlockErr != nil {
|
||||
err = multierror.Append(err, unlockErr)
|
||||
}
|
||||
|
||||
@@ -468,7 +468,7 @@ func (c *RemoteClient) lock() (string, error) {
|
||||
// If we lose the lock to due communication issues with the consul agent,
|
||||
// attempt to immediately reacquire the lock. Put will verify the integrity
|
||||
// of the state by using a CAS operation.
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
ctx, cancel := context.WithCancel(ctx)
|
||||
c.monitorCancel = cancel
|
||||
c.monitorWG.Add(1)
|
||||
go func() {
|
||||
@@ -485,7 +485,7 @@ func (c *RemoteClient) lock() (string, error) {
|
||||
c.sessionCancel()
|
||||
|
||||
c.consulLock = nil
|
||||
_, err := c.lock()
|
||||
_, err := c.lock(ctx)
|
||||
c.mu.Unlock()
|
||||
|
||||
if err != nil {
|
||||
@@ -551,7 +551,7 @@ func (c *RemoteClient) createSession() (string, error) {
|
||||
return id, nil
|
||||
}
|
||||
|
||||
func (c *RemoteClient) Unlock(id string) error {
|
||||
func (c *RemoteClient) Unlock(ctx context.Context, id string) error {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
|
||||
@@ -559,12 +559,12 @@ func (c *RemoteClient) Unlock(id string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
return c.unlock(id)
|
||||
return c.unlock(ctx, id)
|
||||
}
|
||||
|
||||
// the unlock implementation.
|
||||
// Only to be called while holding Client.mu
|
||||
func (c *RemoteClient) unlock(id string) error {
|
||||
func (c *RemoteClient) unlock(_ context.Context, id string) error {
|
||||
// This method can be called in two circumstances:
|
||||
// - when the plan apply or destroy operation finishes and the lock needs to be released,
|
||||
// the watchdog stopped and the session closed
|
||||
|
||||
@@ -312,14 +312,14 @@ func TestConsul_destroyLock(t *testing.T) {
|
||||
clientA := s.(*remote.State).Client.(*RemoteClient)
|
||||
|
||||
info := statemgr.NewLockInfo()
|
||||
id, err := clientA.Lock(info)
|
||||
id, err := clientA.Lock(t.Context(), info)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
lockPath := clientA.Path + lockSuffix
|
||||
|
||||
if err := clientA.Unlock(id); err != nil {
|
||||
if err := clientA.Unlock(t.Context(), id); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
@@ -335,18 +335,18 @@ func TestConsul_destroyLock(t *testing.T) {
|
||||
clientB := s.(*remote.State).Client.(*RemoteClient)
|
||||
|
||||
info = statemgr.NewLockInfo()
|
||||
id, err = clientA.Lock(info)
|
||||
id, err = clientA.Lock(t.Context(), info)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if err := clientB.Unlock(id); err != nil {
|
||||
if err := clientB.Unlock(t.Context(), id); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
testLock(clientA, lockPath)
|
||||
|
||||
err = clientA.Unlock(id)
|
||||
err = clientA.Unlock(t.Context(), id)
|
||||
|
||||
if err == nil {
|
||||
t.Fatal("consul lock should have been lost")
|
||||
@@ -383,7 +383,7 @@ func TestConsul_lostLock(t *testing.T) {
|
||||
|
||||
info := statemgr.NewLockInfo()
|
||||
info.Operation = "test-lost-lock"
|
||||
id, err := sA.Lock(info)
|
||||
id, err := sA.Lock(t.Context(), info)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -403,7 +403,7 @@ func TestConsul_lostLock(t *testing.T) {
|
||||
|
||||
<-reLocked
|
||||
|
||||
if err := sA.Unlock(id); err != nil {
|
||||
if err := sA.Unlock(t.Context(), id); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
@@ -435,7 +435,7 @@ func TestConsul_lostLockConnection(t *testing.T) {
|
||||
|
||||
info := statemgr.NewLockInfo()
|
||||
info.Operation = "test-lost-lock-connection"
|
||||
id, err := s.Lock(info)
|
||||
id, err := s.Lock(t.Context(), info)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -449,7 +449,7 @@ func TestConsul_lostLockConnection(t *testing.T) {
|
||||
<-dialed
|
||||
}
|
||||
|
||||
if err := s.Unlock(id); err != nil {
|
||||
if err := s.Unlock(t.Context(), id); err != nil {
|
||||
t.Fatal("unlock error:", err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -114,14 +114,14 @@ func (b *Backend) StateMgr(ctx context.Context, name string) (statemgr.Full, err
|
||||
|
||||
// Local helper function so we can call it multiple places
|
||||
lockUnlock := func(e error) error {
|
||||
if err := stateMgr.Unlock(lockId); err != nil {
|
||||
if err := stateMgr.Unlock(ctx, lockId); err != nil {
|
||||
return fmt.Errorf(unlockErrMsg, err, lockId)
|
||||
}
|
||||
return e
|
||||
}
|
||||
|
||||
// Grab the value
|
||||
if err := stateMgr.RefreshState(); err != nil {
|
||||
if err := stateMgr.RefreshState(ctx); err != nil {
|
||||
err = lockUnlock(err)
|
||||
return nil, err
|
||||
}
|
||||
@@ -132,7 +132,7 @@ func (b *Backend) StateMgr(ctx context.Context, name string) (statemgr.Full, err
|
||||
err = lockUnlock(err)
|
||||
return nil, err
|
||||
}
|
||||
if err := stateMgr.PersistState(nil); err != nil {
|
||||
if err := stateMgr.PersistState(ctx, nil); err != nil {
|
||||
err = lockUnlock(err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -93,7 +93,7 @@ func (b *Backend) client(name string) (*remoteClient, error) {
|
||||
|
||||
// StateMgr reads and returns the named state from GCS. If the named state does
|
||||
// not yet exist, a new state file is created.
|
||||
func (b *Backend) StateMgr(_ context.Context, name string) (statemgr.Full, error) {
|
||||
func (b *Backend) StateMgr(ctx context.Context, name string) (statemgr.Full, error) {
|
||||
c, err := b.client(name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -102,7 +102,7 @@ func (b *Backend) StateMgr(_ context.Context, name string) (statemgr.Full, error
|
||||
st := remote.NewState(c, b.encryption)
|
||||
|
||||
// Grab the value
|
||||
if err := st.RefreshState(); err != nil {
|
||||
if err := st.RefreshState(ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -111,14 +111,14 @@ func (b *Backend) StateMgr(_ context.Context, name string) (statemgr.Full, error
|
||||
|
||||
lockInfo := statemgr.NewLockInfo()
|
||||
lockInfo.Operation = "init"
|
||||
lockID, err := st.Lock(lockInfo)
|
||||
lockID, err := st.Lock(ctx, lockInfo)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Local helper function so we can call it multiple places
|
||||
unlock := func(baseErr error) error {
|
||||
if err := st.Unlock(lockID); err != nil {
|
||||
if err := st.Unlock(ctx, lockID); err != nil {
|
||||
const unlockErrMsg = `%v
|
||||
Additionally, unlocking the state file on Google Cloud Storage failed:
|
||||
|
||||
@@ -138,7 +138,7 @@ func (b *Backend) StateMgr(_ context.Context, name string) (statemgr.Full, error
|
||||
if err := st.WriteState(states.NewState()); err != nil {
|
||||
return nil, unlock(err)
|
||||
}
|
||||
if err := st.PersistState(nil); err != nil {
|
||||
if err := st.PersistState(ctx, nil); err != nil {
|
||||
return nil, unlock(err)
|
||||
}
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ package http
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto/md5"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
@@ -43,7 +44,7 @@ type httpClient struct {
|
||||
jsonLockInfo []byte
|
||||
}
|
||||
|
||||
func (c *httpClient) httpRequest(method string, url *url.URL, data []byte, what string) (*http.Response, error) {
|
||||
func (c *httpClient) httpRequest(ctx context.Context, method string, url *url.URL, data []byte, what string) (*http.Response, error) {
|
||||
var body interface{}
|
||||
if len(data) > 0 {
|
||||
body = data
|
||||
@@ -52,7 +53,7 @@ func (c *httpClient) httpRequest(method string, url *url.URL, data []byte, what
|
||||
log.Printf("[DEBUG] Executing HTTP remote state request for: %q", what)
|
||||
|
||||
// Create the request
|
||||
req, err := retryablehttp.NewRequest(method, url.String(), body)
|
||||
req, err := retryablehttp.NewRequestWithContext(ctx, method, url.String(), body)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Failed to make %s HTTP request: %w", what, err)
|
||||
}
|
||||
@@ -89,14 +90,14 @@ func (c *httpClient) httpRequest(method string, url *url.URL, data []byte, what
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
func (c *httpClient) Lock(info *statemgr.LockInfo) (string, error) {
|
||||
func (c *httpClient) Lock(ctx context.Context, info *statemgr.LockInfo) (string, error) {
|
||||
if c.LockURL == nil {
|
||||
return "", nil
|
||||
}
|
||||
c.lockID = ""
|
||||
|
||||
jsonLockInfo := info.Marshal()
|
||||
resp, err := c.httpRequest(c.LockMethod, c.LockURL, jsonLockInfo, "lock")
|
||||
resp, err := c.httpRequest(ctx, c.LockMethod, c.LockURL, jsonLockInfo, "lock")
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
@@ -139,11 +140,14 @@ func (c *httpClient) Lock(info *statemgr.LockInfo) (string, error) {
|
||||
}
|
||||
}
|
||||
|
||||
func (c *httpClient) Unlock(id string) error {
|
||||
func (c *httpClient) Unlock(ctx context.Context, id string) error {
|
||||
if c.UnlockURL == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
// We must be able to unlock when already cancelled
|
||||
ctx = context.WithoutCancel(ctx)
|
||||
|
||||
var lockInfo statemgr.LockInfo
|
||||
|
||||
// force unlock command does not instantiate statemgr.LockInfo
|
||||
@@ -162,7 +166,7 @@ func (c *httpClient) Unlock(id string) error {
|
||||
|
||||
lockInfo.ID = id
|
||||
|
||||
resp, err := c.httpRequest(c.UnlockMethod, c.UnlockURL, lockInfo.Marshal(), "unlock")
|
||||
resp, err := c.httpRequest(ctx, c.UnlockMethod, c.UnlockURL, lockInfo.Marshal(), "unlock")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -178,7 +182,7 @@ func (c *httpClient) Unlock(id string) error {
|
||||
}
|
||||
|
||||
func (c *httpClient) Get() (*remote.Payload, error) {
|
||||
resp, err := c.httpRequest(http.MethodGet, c.URL, nil, "get state")
|
||||
resp, err := c.httpRequest(context.TODO(), http.MethodGet, c.URL, nil, "get state")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -263,7 +267,7 @@ func (c *httpClient) Put(data []byte) error {
|
||||
if c.UpdateMethod != "" {
|
||||
method = c.UpdateMethod
|
||||
}
|
||||
resp, err := c.httpRequest(method, &base, data, "upload state")
|
||||
resp, err := c.httpRequest(context.TODO(), method, &base, data, "upload state")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -281,7 +285,7 @@ func (c *httpClient) Put(data []byte) error {
|
||||
|
||||
func (c *httpClient) Delete() error {
|
||||
// Make the request
|
||||
resp, err := c.httpRequest(http.MethodDelete, c.URL, nil, "delete state")
|
||||
resp, err := c.httpRequest(context.TODO(), http.MethodDelete, c.URL, nil, "delete state")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -370,7 +370,7 @@ func TestHttpClient_Unlock(t *testing.T) {
|
||||
jsonLockInfo: tt.jsonLockInfo,
|
||||
}
|
||||
|
||||
err = client.Unlock(tt.lockID)
|
||||
err = client.Unlock(t.Context(), tt.lockID)
|
||||
if tt.expectedErrorMsg != nil && err == nil {
|
||||
// no expected error
|
||||
t.Errorf("UnLock() no expected error = %v", tt.expectedErrorMsg)
|
||||
@@ -474,7 +474,7 @@ func TestHttpClient_lock(t *testing.T) {
|
||||
Client: retryablehttp.NewClient(),
|
||||
}
|
||||
|
||||
lockID, err := client.Lock(tt.lockInfo)
|
||||
lockID, err := client.Lock(t.Context(), tt.lockInfo)
|
||||
if tt.expectedErrorMsg != nil && err == nil {
|
||||
// no expected error
|
||||
t.Errorf("Lock() no expected error = %v", tt.expectedErrorMsg)
|
||||
|
||||
@@ -289,7 +289,7 @@ func TestMTLSServer_NoCertFails(t *testing.T) {
|
||||
}
|
||||
|
||||
opErr := new(net.OpError)
|
||||
err = sm.RefreshState()
|
||||
err = sm.RefreshState(t.Context())
|
||||
if err == nil {
|
||||
t.Fatal("expected error when refreshing state without a client cert")
|
||||
}
|
||||
@@ -358,7 +358,7 @@ func TestMTLSServer_WithCertPasses(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error fetching StateMgr with %s: %v", backend.DefaultStateName, err)
|
||||
}
|
||||
if err = sm.RefreshState(); err != nil {
|
||||
if err = sm.RefreshState(t.Context()); err != nil {
|
||||
t.Fatalf("unexpected error calling RefreshState: %v", err)
|
||||
}
|
||||
state := sm.State()
|
||||
@@ -399,10 +399,10 @@ func TestMTLSServer_WithCertPasses(t *testing.T) {
|
||||
if err = sm.WriteState(state); err != nil {
|
||||
t.Errorf("error writing state: %v", err)
|
||||
}
|
||||
if err = sm.PersistState(nil); err != nil {
|
||||
if err = sm.PersistState(t.Context(), nil); err != nil {
|
||||
t.Errorf("error persisting state: %v", err)
|
||||
}
|
||||
if err = sm.RefreshState(); err != nil {
|
||||
if err = sm.RefreshState(t.Context()); err != nil {
|
||||
t.Errorf("error refreshing state: %v", err)
|
||||
}
|
||||
|
||||
|
||||
@@ -121,7 +121,7 @@ func (b *Backend) DeleteWorkspace(_ context.Context, name string, _ bool) error
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *Backend) StateMgr(_ context.Context, name string) (statemgr.Full, error) {
|
||||
func (b *Backend) StateMgr(ctx context.Context, name string) (statemgr.Full, error) {
|
||||
states.Lock()
|
||||
defer states.Unlock()
|
||||
|
||||
@@ -139,14 +139,14 @@ func (b *Backend) StateMgr(_ context.Context, name string) (statemgr.Full, error
|
||||
// take a lock and create a new state if it doesn't exist.
|
||||
lockInfo := statemgr.NewLockInfo()
|
||||
lockInfo.Operation = "init"
|
||||
lockID, err := s.Lock(lockInfo)
|
||||
lockID, err := s.Lock(ctx, lockInfo)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to lock inmem state: %w", err)
|
||||
}
|
||||
|
||||
// Local helper function so we can call it multiple places
|
||||
lockUnlock := func(parent error) error {
|
||||
if err := s.Unlock(lockID); err != nil {
|
||||
if err := s.Unlock(ctx, lockID); err != nil {
|
||||
return errors.Join(
|
||||
fmt.Errorf("error unlocking inmem state: %w", err),
|
||||
parent,
|
||||
@@ -161,7 +161,7 @@ func (b *Backend) StateMgr(_ context.Context, name string) (statemgr.Full, error
|
||||
err = lockUnlock(err)
|
||||
return nil, err
|
||||
}
|
||||
if err := s.PersistState(nil); err != nil {
|
||||
if err := s.PersistState(context.WithoutCancel(ctx), nil); err != nil {
|
||||
err = lockUnlock(err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -88,11 +88,11 @@ func TestRemoteState(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if err := s.PersistState(nil); err != nil {
|
||||
if err := s.PersistState(t.Context(), nil); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if err := s.RefreshState(); err != nil {
|
||||
if err := s.RefreshState(t.Context()); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
package inmem
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/md5"
|
||||
|
||||
"github.com/opentofu/opentofu/internal/states/remote"
|
||||
@@ -44,9 +45,9 @@ func (c *RemoteClient) Delete() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *RemoteClient) Lock(info *statemgr.LockInfo) (string, error) {
|
||||
func (c *RemoteClient) Lock(_ context.Context, info *statemgr.LockInfo) (string, error) {
|
||||
return locks.lock(c.Name, info)
|
||||
}
|
||||
func (c *RemoteClient) Unlock(id string) error {
|
||||
func (c *RemoteClient) Unlock(_ context.Context, id string) error {
|
||||
return locks.unlock(c.Name, id)
|
||||
}
|
||||
|
||||
@@ -78,7 +78,7 @@ func (b *Backend) DeleteWorkspace(_ context.Context, name string, _ bool) error
|
||||
return client.Delete()
|
||||
}
|
||||
|
||||
func (b *Backend) StateMgr(_ context.Context, name string) (statemgr.Full, error) {
|
||||
func (b *Backend) StateMgr(ctx context.Context, name string) (statemgr.Full, error) {
|
||||
c, err := b.remoteClient(name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -87,7 +87,7 @@ func (b *Backend) StateMgr(_ context.Context, name string) (statemgr.Full, error
|
||||
stateMgr := remote.NewState(c, b.encryption)
|
||||
|
||||
// Grab the value
|
||||
if err := stateMgr.RefreshState(); err != nil {
|
||||
if err := stateMgr.RefreshState(ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -96,7 +96,7 @@ func (b *Backend) StateMgr(_ context.Context, name string) (statemgr.Full, error
|
||||
|
||||
lockInfo := statemgr.NewLockInfo()
|
||||
lockInfo.Operation = "init"
|
||||
lockID, err := stateMgr.Lock(lockInfo)
|
||||
lockID, err := stateMgr.Lock(ctx, lockInfo)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -108,7 +108,7 @@ func (b *Backend) StateMgr(_ context.Context, name string) (statemgr.Full, error
|
||||
|
||||
// Local helper function so we can call it multiple places
|
||||
unlock := func(baseErr error) error {
|
||||
if err := stateMgr.Unlock(lockID); err != nil {
|
||||
if err := stateMgr.Unlock(ctx, lockID); err != nil {
|
||||
const unlockErrMsg = `%v
|
||||
Additionally, unlocking the state in Kubernetes failed:
|
||||
|
||||
@@ -128,7 +128,7 @@ func (b *Backend) StateMgr(_ context.Context, name string) (statemgr.Full, error
|
||||
if err := stateMgr.WriteState(states.NewState()); err != nil {
|
||||
return nil, unlock(err)
|
||||
}
|
||||
if err := stateMgr.PersistState(nil); err != nil {
|
||||
if err := stateMgr.PersistState(context.WithoutCancel(ctx), nil); err != nil {
|
||||
return nil, unlock(err)
|
||||
}
|
||||
|
||||
|
||||
@@ -111,7 +111,7 @@ func TestBackendLocksSoak(t *testing.T) {
|
||||
li.Who = fmt.Sprintf("client-%v", n)
|
||||
|
||||
for i := 0; i < lockAttempts; i++ {
|
||||
id, err := locker.Lock(li)
|
||||
id, err := locker.Lock(t.Context(), li)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
@@ -119,7 +119,7 @@ func TestBackendLocksSoak(t *testing.T) {
|
||||
// hold onto the lock for a little bit
|
||||
time.Sleep(time.Duration(rand.Intn(10)) * time.Microsecond)
|
||||
|
||||
err = locker.Unlock(id)
|
||||
err = locker.Unlock(t.Context(), id)
|
||||
if err != nil {
|
||||
t.Errorf("failed to unlock: %v", err)
|
||||
}
|
||||
|
||||
@@ -151,8 +151,7 @@ func (c *RemoteClient) Delete() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *RemoteClient) Lock(info *statemgr.LockInfo) (string, error) {
|
||||
ctx := context.Background()
|
||||
func (c *RemoteClient) Lock(ctx context.Context, info *statemgr.LockInfo) (string, error) {
|
||||
leaseName, err := c.createLeaseName()
|
||||
if err != nil {
|
||||
return "", err
|
||||
@@ -213,7 +212,9 @@ func (c *RemoteClient) Lock(info *statemgr.LockInfo) (string, error) {
|
||||
return info.ID, err
|
||||
}
|
||||
|
||||
func (c *RemoteClient) Unlock(id string) error {
|
||||
func (c *RemoteClient) Unlock(ctx context.Context, id string) error {
|
||||
ctx = context.WithoutCancel(ctx)
|
||||
|
||||
leaseName, err := c.createLeaseName()
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -242,7 +243,7 @@ func (c *RemoteClient) Unlock(id string) error {
|
||||
lease.Spec.HolderIdentity = nil
|
||||
removeLockInfo(lease)
|
||||
|
||||
_, err = c.kubernetesLeaseClient.Update(context.Background(), lease, metav1.UpdateOptions{})
|
||||
_, err = c.kubernetesLeaseClient.Update(ctx, lease, metav1.UpdateOptions{})
|
||||
if err != nil {
|
||||
lockErr.Err = err
|
||||
return lockErr
|
||||
|
||||
@@ -82,7 +82,7 @@ func TestForceUnlock(t *testing.T) {
|
||||
info.Operation = "test"
|
||||
info.Who = "clientA"
|
||||
|
||||
lockID, err := s1.Lock(info)
|
||||
lockID, err := s1.Lock(t.Context(), info)
|
||||
if err != nil {
|
||||
t.Fatal("unable to get initial lock:", err)
|
||||
}
|
||||
@@ -93,7 +93,7 @@ func TestForceUnlock(t *testing.T) {
|
||||
t.Fatal("failed to get default state to force unlock:", err)
|
||||
}
|
||||
|
||||
if err := s2.Unlock(lockID); err != nil {
|
||||
if err := s2.Unlock(t.Context(), lockID); err != nil {
|
||||
t.Fatal("failed to force-unlock default state")
|
||||
}
|
||||
|
||||
@@ -108,7 +108,7 @@ func TestForceUnlock(t *testing.T) {
|
||||
info.Operation = "test"
|
||||
info.Who = "clientA"
|
||||
|
||||
lockID, err = s1.Lock(info)
|
||||
lockID, err = s1.Lock(t.Context(), info)
|
||||
if err != nil {
|
||||
t.Fatal("unable to get initial lock:", err)
|
||||
}
|
||||
@@ -119,7 +119,7 @@ func TestForceUnlock(t *testing.T) {
|
||||
t.Fatal("failed to get named state to force unlock:", err)
|
||||
}
|
||||
|
||||
if err = s2.Unlock(lockID); err != nil {
|
||||
if err = s2.Unlock(t.Context(), lockID); err != nil {
|
||||
t.Fatal("failed to force-unlock named state")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -141,21 +141,21 @@ func (b *Backend) StateMgr(ctx context.Context, name string) (statemgr.Full, err
|
||||
// take a lock on this state while we write it
|
||||
lockInfo := statemgr.NewLockInfo()
|
||||
lockInfo.Operation = "init"
|
||||
lockId, err := client.Lock(lockInfo)
|
||||
lockId, err := client.Lock(ctx, lockInfo)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to lock OSS state: %w", err)
|
||||
}
|
||||
|
||||
// Local helper function so we can call it multiple places
|
||||
lockUnlock := func(e error) error {
|
||||
if err := stateMgr.Unlock(lockId); err != nil {
|
||||
if err := stateMgr.Unlock(ctx, lockId); err != nil {
|
||||
return fmt.Errorf(strings.TrimSpace(stateUnlockError), lockId, err)
|
||||
}
|
||||
return e
|
||||
}
|
||||
|
||||
// Grab the value
|
||||
if err := stateMgr.RefreshState(); err != nil {
|
||||
if err := stateMgr.RefreshState(ctx); err != nil {
|
||||
err = lockUnlock(err)
|
||||
return nil, err
|
||||
}
|
||||
@@ -166,7 +166,7 @@ func (b *Backend) StateMgr(ctx context.Context, name string) (statemgr.Full, err
|
||||
err = lockUnlock(err)
|
||||
return nil, err
|
||||
}
|
||||
if err := stateMgr.PersistState(nil); err != nil {
|
||||
if err := stateMgr.PersistState(context.WithoutCancel(ctx), nil); err != nil {
|
||||
err = lockUnlock(err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ package oss
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto/md5"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
@@ -149,7 +150,7 @@ func (c *RemoteClient) Delete() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *RemoteClient) Lock(info *statemgr.LockInfo) (string, error) {
|
||||
func (c *RemoteClient) Lock(_ context.Context, info *statemgr.LockInfo) (string, error) {
|
||||
if c.otsTable == "" {
|
||||
return "", nil
|
||||
}
|
||||
@@ -360,7 +361,7 @@ func (c *RemoteClient) getLockInfo() (*statemgr.LockInfo, error) {
|
||||
}
|
||||
return lockInfo, nil
|
||||
}
|
||||
func (c *RemoteClient) Unlock(id string) error {
|
||||
func (c *RemoteClient) Unlock(_ context.Context, id string) error {
|
||||
if c.otsTable == "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -123,7 +123,7 @@ func TestRemoteClientLocks_multipleStates(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if _, err := s1.Lock(statemgr.NewLockInfo()); err != nil {
|
||||
if _, err := s1.Lock(t.Context(), statemgr.NewLockInfo()); err != nil {
|
||||
t.Fatal("failed to get lock for s1:", err)
|
||||
}
|
||||
|
||||
@@ -132,7 +132,7 @@ func TestRemoteClientLocks_multipleStates(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if _, err := s2.Lock(statemgr.NewLockInfo()); err != nil {
|
||||
if _, err := s2.Lock(t.Context(), statemgr.NewLockInfo()); err != nil {
|
||||
t.Fatal("failed to get lock for s2:", err)
|
||||
}
|
||||
}
|
||||
@@ -175,7 +175,7 @@ func TestRemoteForceUnlock(t *testing.T) {
|
||||
info.Operation = "test"
|
||||
info.Who = "clientA"
|
||||
|
||||
lockID, err := s1.Lock(info)
|
||||
lockID, err := s1.Lock(t.Context(), info)
|
||||
if err != nil {
|
||||
t.Fatal("unable to get initial lock:", err)
|
||||
}
|
||||
@@ -186,7 +186,7 @@ func TestRemoteForceUnlock(t *testing.T) {
|
||||
t.Fatal("failed to get default state to force unlock:", err)
|
||||
}
|
||||
|
||||
if err := s2.Unlock(lockID); err != nil {
|
||||
if err := s2.Unlock(t.Context(), lockID); err != nil {
|
||||
t.Fatal("failed to force-unlock default state")
|
||||
}
|
||||
|
||||
@@ -201,7 +201,7 @@ func TestRemoteForceUnlock(t *testing.T) {
|
||||
info.Operation = "test"
|
||||
info.Who = "clientA"
|
||||
|
||||
lockID, err = s1.Lock(info)
|
||||
lockID, err = s1.Lock(t.Context(), info)
|
||||
if err != nil {
|
||||
t.Fatal("unable to get initial lock:", err)
|
||||
}
|
||||
@@ -212,7 +212,7 @@ func TestRemoteForceUnlock(t *testing.T) {
|
||||
t.Fatal("failed to get named state to force unlock:", err)
|
||||
}
|
||||
|
||||
if err = s2.Unlock(lockID); err != nil {
|
||||
if err = s2.Unlock(t.Context(), lockID); err != nil {
|
||||
t.Fatal("failed to force-unlock named state")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -92,14 +92,14 @@ func (b *Backend) StateMgr(ctx context.Context, name string) (statemgr.Full, err
|
||||
if !exists {
|
||||
lockInfo := statemgr.NewLockInfo()
|
||||
lockInfo.Operation = "init"
|
||||
lockId, err := stateMgr.Lock(lockInfo)
|
||||
lockId, err := stateMgr.Lock(ctx, lockInfo)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to lock state in Postgres: %w", err)
|
||||
}
|
||||
|
||||
// Local helper function so we can call it multiple places
|
||||
lockUnlock := func(parent error) error {
|
||||
if err := stateMgr.Unlock(lockId); err != nil {
|
||||
if err := stateMgr.Unlock(ctx, lockId); err != nil {
|
||||
return fmt.Errorf("error unlocking Postgres state: %w", err)
|
||||
}
|
||||
return parent
|
||||
@@ -110,7 +110,7 @@ func (b *Backend) StateMgr(ctx context.Context, name string) (statemgr.Full, err
|
||||
err = lockUnlock(err)
|
||||
return nil, err
|
||||
}
|
||||
if err := stateMgr.PersistState(nil); err != nil {
|
||||
if err := stateMgr.PersistState(context.WithoutCancel(ctx), nil); err != nil {
|
||||
err = lockUnlock(err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -112,7 +112,7 @@ func TestRemote_applyBasic(t *testing.T) {
|
||||
|
||||
stateMgr, _ := b.StateMgr(t.Context(), backend.DefaultStateName)
|
||||
// An error suggests that the state was not unlocked after apply
|
||||
if _, err := stateMgr.Lock(statemgr.NewLockInfo()); err != nil {
|
||||
if _, err := stateMgr.Lock(t.Context(), statemgr.NewLockInfo()); err != nil {
|
||||
t.Fatalf("unexpected error locking state after apply: %s", err.Error())
|
||||
}
|
||||
}
|
||||
@@ -140,7 +140,7 @@ func TestRemote_applyCanceled(t *testing.T) {
|
||||
}
|
||||
|
||||
stateMgr, _ := b.StateMgr(t.Context(), backend.DefaultStateName)
|
||||
if _, err := stateMgr.Lock(statemgr.NewLockInfo()); err != nil {
|
||||
if _, err := stateMgr.Lock(t.Context(), statemgr.NewLockInfo()); err != nil {
|
||||
t.Fatalf("unexpected error locking state after cancelling apply: %s", err.Error())
|
||||
}
|
||||
}
|
||||
@@ -488,7 +488,7 @@ func TestRemote_applyWithExclude(t *testing.T) {
|
||||
|
||||
stateMgr, _ := b.StateMgr(t.Context(), backend.DefaultStateName)
|
||||
// An error suggests that the state was not unlocked after apply
|
||||
if _, err := stateMgr.Lock(statemgr.NewLockInfo()); err != nil {
|
||||
if _, err := stateMgr.Lock(t.Context(), statemgr.NewLockInfo()); err != nil {
|
||||
t.Fatalf("unexpected error locking state after failed apply: %s", err.Error())
|
||||
}
|
||||
}
|
||||
@@ -654,7 +654,7 @@ func TestRemote_applyNoConfig(t *testing.T) {
|
||||
|
||||
stateMgr, _ := b.StateMgr(t.Context(), backend.DefaultStateName)
|
||||
// An error suggests that the state was not unlocked after apply
|
||||
if _, err := stateMgr.Lock(statemgr.NewLockInfo()); err != nil {
|
||||
if _, err := stateMgr.Lock(t.Context(), statemgr.NewLockInfo()); err != nil {
|
||||
t.Fatalf("unexpected error locking state after failed apply: %s", err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,7 +64,7 @@ func (b *Remote) LocalRun(ctx context.Context, op *backend.Operation) (*backend.
|
||||
}()
|
||||
|
||||
log.Printf("[TRACE] backend/remote: reading remote state for workspace %q", remoteWorkspaceName)
|
||||
if err := stateMgr.RefreshState(); err != nil {
|
||||
if err := stateMgr.RefreshState(ctx); err != nil {
|
||||
diags = diags.Append(fmt.Errorf("error loading state: %w", err))
|
||||
return nil, nil, diags
|
||||
}
|
||||
|
||||
@@ -228,7 +228,7 @@ func TestRemoteContextWithVars(t *testing.T) {
|
||||
// When Context() returns an error, it should unlock the state,
|
||||
// so re-locking it is expected to succeed.
|
||||
stateMgr, _ := b.StateMgr(t.Context(), backend.DefaultStateName)
|
||||
if _, err := stateMgr.Lock(statemgr.NewLockInfo()); err != nil {
|
||||
if _, err := stateMgr.Lock(t.Context(), statemgr.NewLockInfo()); err != nil {
|
||||
t.Fatalf("unexpected error locking state: %s", err.Error())
|
||||
}
|
||||
} else {
|
||||
@@ -237,7 +237,7 @@ func TestRemoteContextWithVars(t *testing.T) {
|
||||
}
|
||||
// When Context() succeeds, this should fail w/ "workspace already locked"
|
||||
stateMgr, _ := b.StateMgr(t.Context(), backend.DefaultStateName)
|
||||
if _, err := stateMgr.Lock(statemgr.NewLockInfo()); err == nil {
|
||||
if _, err := stateMgr.Lock(t.Context(), statemgr.NewLockInfo()); err == nil {
|
||||
t.Fatal("unexpected success locking state after Context")
|
||||
}
|
||||
}
|
||||
@@ -445,7 +445,7 @@ func TestRemoteVariablesDoNotOverride(t *testing.T) {
|
||||
}
|
||||
// When Context() succeeds, this should fail w/ "workspace already locked"
|
||||
stateMgr, _ := b.StateMgr(t.Context(), backend.DefaultStateName)
|
||||
if _, err := stateMgr.Lock(statemgr.NewLockInfo()); err == nil {
|
||||
if _, err := stateMgr.Lock(t.Context(), statemgr.NewLockInfo()); err == nil {
|
||||
t.Fatal("unexpected success locking state after Context")
|
||||
}
|
||||
|
||||
|
||||
@@ -97,7 +97,7 @@ func TestRemote_planBasic(t *testing.T) {
|
||||
|
||||
stateMgr, _ := b.StateMgr(t.Context(), backend.DefaultStateName)
|
||||
// An error suggests that the state was not unlocked after the operation finished
|
||||
if _, err := stateMgr.Lock(statemgr.NewLockInfo()); err != nil {
|
||||
if _, err := stateMgr.Lock(t.Context(), statemgr.NewLockInfo()); err != nil {
|
||||
t.Fatalf("unexpected error locking state after successful plan: %s", err.Error())
|
||||
}
|
||||
}
|
||||
@@ -126,7 +126,7 @@ func TestRemote_planCanceled(t *testing.T) {
|
||||
|
||||
stateMgr, _ := b.StateMgr(t.Context(), backend.DefaultStateName)
|
||||
// An error suggests that the state was not unlocked after the operation finished
|
||||
if _, err := stateMgr.Lock(statemgr.NewLockInfo()); err != nil {
|
||||
if _, err := stateMgr.Lock(t.Context(), statemgr.NewLockInfo()); err != nil {
|
||||
t.Fatalf("unexpected error locking state after cancelled plan: %s", err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -382,13 +382,13 @@ func TestRemote_Unlock_ignoreVersion(t *testing.T) {
|
||||
t.Fatalf("error: %v", err)
|
||||
}
|
||||
|
||||
lockID, err := state.Lock(statemgr.NewLockInfo())
|
||||
lockID, err := state.Lock(t.Context(), statemgr.NewLockInfo())
|
||||
if err != nil {
|
||||
t.Fatalf("error: %v", err)
|
||||
}
|
||||
|
||||
// this should succeed since the version conflict is ignored
|
||||
if err = state.Unlock(lockID); err != nil {
|
||||
if err = state.Unlock(t.Context(), lockID); err != nil {
|
||||
t.Fatalf("error: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -165,7 +165,7 @@ func TestBackendStates(t *testing.T, b Backend) {
|
||||
if err != nil {
|
||||
t.Fatalf("error: %s", err)
|
||||
}
|
||||
if err := foo.RefreshState(); err != nil {
|
||||
if err := foo.RefreshState(t.Context()); err != nil {
|
||||
t.Fatalf("bad: %s", err)
|
||||
}
|
||||
if v := foo.State(); v.HasManagedResourceInstanceObjects() {
|
||||
@@ -176,7 +176,7 @@ func TestBackendStates(t *testing.T, b Backend) {
|
||||
if err != nil {
|
||||
t.Fatalf("error: %s", err)
|
||||
}
|
||||
if err := bar.RefreshState(); err != nil {
|
||||
if err := bar.RefreshState(t.Context()); err != nil {
|
||||
t.Fatalf("bad: %s", err)
|
||||
}
|
||||
if v := bar.State(); v.HasManagedResourceInstanceObjects() {
|
||||
@@ -194,7 +194,7 @@ func TestBackendStates(t *testing.T, b Backend) {
|
||||
if err := foo.WriteState(fooState); err != nil {
|
||||
t.Fatal("error writing foo state:", err)
|
||||
}
|
||||
if err := foo.PersistState(nil); err != nil {
|
||||
if err := foo.PersistState(t.Context(), nil); err != nil {
|
||||
t.Fatal("error persisting foo state:", err)
|
||||
}
|
||||
|
||||
@@ -223,12 +223,12 @@ func TestBackendStates(t *testing.T, b Backend) {
|
||||
if err := bar.WriteState(barState); err != nil {
|
||||
t.Fatalf("bad: %s", err)
|
||||
}
|
||||
if err := bar.PersistState(nil); err != nil {
|
||||
if err := bar.PersistState(t.Context(), nil); err != nil {
|
||||
t.Fatalf("bad: %s", err)
|
||||
}
|
||||
|
||||
// verify that foo is unchanged with the existing state manager
|
||||
if err := foo.RefreshState(); err != nil {
|
||||
if err := foo.RefreshState(t.Context()); err != nil {
|
||||
t.Fatal("error refreshing foo:", err)
|
||||
}
|
||||
fooState = foo.State()
|
||||
@@ -241,7 +241,7 @@ func TestBackendStates(t *testing.T, b Backend) {
|
||||
if err != nil {
|
||||
t.Fatal("error re-fetching state:", err)
|
||||
}
|
||||
if err := foo.RefreshState(); err != nil {
|
||||
if err := foo.RefreshState(t.Context()); err != nil {
|
||||
t.Fatal("error refreshing foo:", err)
|
||||
}
|
||||
fooState = foo.State()
|
||||
@@ -254,7 +254,7 @@ func TestBackendStates(t *testing.T, b Backend) {
|
||||
if err != nil {
|
||||
t.Fatal("error re-fetching state:", err)
|
||||
}
|
||||
if err := bar.RefreshState(); err != nil {
|
||||
if err := bar.RefreshState(t.Context()); err != nil {
|
||||
t.Fatal("error refreshing bar:", err)
|
||||
}
|
||||
barState = bar.State()
|
||||
@@ -298,7 +298,7 @@ func TestBackendStates(t *testing.T, b Backend) {
|
||||
if err != nil {
|
||||
t.Fatalf("error: %s", err)
|
||||
}
|
||||
if err := foo.RefreshState(); err != nil {
|
||||
if err := foo.RefreshState(t.Context()); err != nil {
|
||||
t.Fatalf("bad: %s", err)
|
||||
}
|
||||
if v := foo.State(); v.HasManagedResourceInstanceObjects() {
|
||||
@@ -371,7 +371,7 @@ func testLocksInWorkspace(t *testing.T, b1, b2 Backend, testForceUnlock bool, wo
|
||||
if err != nil {
|
||||
t.Fatalf("error: %s", err)
|
||||
}
|
||||
if err := b1StateMgr.RefreshState(); err != nil {
|
||||
if err := b1StateMgr.RefreshState(t.Context()); err != nil {
|
||||
t.Fatalf("bad: %s", err)
|
||||
}
|
||||
|
||||
@@ -387,7 +387,7 @@ func testLocksInWorkspace(t *testing.T, b1, b2 Backend, testForceUnlock bool, wo
|
||||
if err != nil {
|
||||
t.Fatalf("error: %s", err)
|
||||
}
|
||||
if err := b2StateMgr.RefreshState(); err != nil {
|
||||
if err := b2StateMgr.RefreshState(t.Context()); err != nil {
|
||||
t.Fatalf("bad: %s", err)
|
||||
}
|
||||
|
||||
@@ -403,7 +403,7 @@ func testLocksInWorkspace(t *testing.T, b1, b2 Backend, testForceUnlock bool, wo
|
||||
infoB.Operation = "test"
|
||||
infoB.Who = "clientB"
|
||||
|
||||
lockIDA, err := lockerA.Lock(infoA)
|
||||
lockIDA, err := lockerA.Lock(t.Context(), infoA)
|
||||
if err != nil {
|
||||
t.Fatal("unable to get initial lock:", err)
|
||||
}
|
||||
@@ -422,17 +422,17 @@ func testLocksInWorkspace(t *testing.T, b1, b2 Backend, testForceUnlock bool, wo
|
||||
return
|
||||
}
|
||||
|
||||
_, err = lockerB.Lock(infoB)
|
||||
_, err = lockerB.Lock(t.Context(), infoB)
|
||||
if err == nil {
|
||||
_ = lockerA.Unlock(lockIDA) // test already failed, no need to check err further
|
||||
_ = lockerA.Unlock(t.Context(), lockIDA) // test already failed, no need to check err further
|
||||
t.Fatal("client B obtained lock while held by client A")
|
||||
}
|
||||
|
||||
if err := lockerA.Unlock(lockIDA); err != nil {
|
||||
if err := lockerA.Unlock(t.Context(), lockIDA); err != nil {
|
||||
t.Fatal("error unlocking client A", err)
|
||||
}
|
||||
|
||||
lockIDB, err := lockerB.Lock(infoB)
|
||||
lockIDB, err := lockerB.Lock(t.Context(), infoB)
|
||||
if err != nil {
|
||||
t.Fatal("unable to obtain lock from client B")
|
||||
}
|
||||
@@ -441,7 +441,7 @@ func testLocksInWorkspace(t *testing.T, b1, b2 Backend, testForceUnlock bool, wo
|
||||
t.Errorf("duplicate lock IDs: %q", lockIDB)
|
||||
}
|
||||
|
||||
if err = lockerB.Unlock(lockIDB); err != nil {
|
||||
if err = lockerB.Unlock(t.Context(), lockIDB); err != nil {
|
||||
t.Fatal("error unlocking client B:", err)
|
||||
}
|
||||
|
||||
@@ -457,18 +457,18 @@ func testLocksInWorkspace(t *testing.T, b1, b2 Backend, testForceUnlock bool, wo
|
||||
panic(err)
|
||||
}
|
||||
|
||||
lockIDA, err = lockerA.Lock(infoA)
|
||||
lockIDA, err = lockerA.Lock(t.Context(), infoA)
|
||||
if err != nil {
|
||||
t.Fatal("unable to get re lock A:", err)
|
||||
}
|
||||
unlock := func() {
|
||||
err := lockerA.Unlock(lockIDA)
|
||||
err := lockerA.Unlock(t.Context(), lockIDA)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
_, err = lockerB.Lock(infoB)
|
||||
_, err = lockerB.Lock(t.Context(), infoB)
|
||||
if err == nil {
|
||||
unlock()
|
||||
t.Fatal("client B obtained lock while held by client A")
|
||||
@@ -481,7 +481,7 @@ func testLocksInWorkspace(t *testing.T, b1, b2 Backend, testForceUnlock bool, wo
|
||||
}
|
||||
|
||||
// try to unlock with the second unlocker, using the ID from the error
|
||||
if err := lockerB.Unlock(infoErr.Info.ID); err != nil {
|
||||
if err := lockerB.Unlock(t.Context(), infoErr.Info.ID); err != nil {
|
||||
unlock()
|
||||
t.Fatalf("could not unlock with the reported ID %q: %s", infoErr.Info.ID, err)
|
||||
}
|
||||
|
||||
@@ -146,7 +146,7 @@ func dataSourceRemoteStateRead(ctx context.Context, d cty.Value, enc encryption.
|
||||
return cty.NilVal, diags
|
||||
}
|
||||
|
||||
if err := state.RefreshState(); err != nil {
|
||||
if err := state.RefreshState(ctx); err != nil {
|
||||
diags = diags.Append(err)
|
||||
return cty.NilVal, diags
|
||||
}
|
||||
|
||||
@@ -116,7 +116,7 @@ func TestCloud_applyBasic(t *testing.T) {
|
||||
|
||||
stateMgr, _ := b.StateMgr(t.Context(), testBackendSingleWorkspaceName)
|
||||
// An error suggests that the state was not unlocked after apply
|
||||
if _, err := stateMgr.Lock(statemgr.NewLockInfo()); err != nil {
|
||||
if _, err := stateMgr.Lock(t.Context(), statemgr.NewLockInfo()); err != nil {
|
||||
t.Fatalf("unexpected error locking state after apply: %s", err.Error())
|
||||
}
|
||||
}
|
||||
@@ -174,7 +174,7 @@ func TestCloud_applyJSONBasic(t *testing.T) {
|
||||
|
||||
stateMgr, _ := b.StateMgr(t.Context(), testBackendSingleWorkspaceName)
|
||||
// An error suggests that the state was not unlocked after apply
|
||||
if _, err := stateMgr.Lock(statemgr.NewLockInfo()); err != nil {
|
||||
if _, err := stateMgr.Lock(t.Context(), statemgr.NewLockInfo()); err != nil {
|
||||
t.Fatalf("unexpected error locking state after apply: %s", err.Error())
|
||||
}
|
||||
}
|
||||
@@ -261,7 +261,7 @@ func TestCloud_applyJSONWithOutputs(t *testing.T) {
|
||||
}
|
||||
stateMgr, _ := b.StateMgr(t.Context(), testBackendSingleWorkspaceName)
|
||||
// An error suggests that the state was not unlocked after apply
|
||||
if _, err := stateMgr.Lock(statemgr.NewLockInfo()); err != nil {
|
||||
if _, err := stateMgr.Lock(t.Context(), statemgr.NewLockInfo()); err != nil {
|
||||
t.Fatalf("unexpected error locking state after apply: %s", err.Error())
|
||||
}
|
||||
}
|
||||
@@ -289,7 +289,7 @@ func TestCloud_applyCanceled(t *testing.T) {
|
||||
}
|
||||
|
||||
stateMgr, _ := b.StateMgr(t.Context(), testBackendSingleWorkspaceName)
|
||||
if _, err := stateMgr.Lock(statemgr.NewLockInfo()); err != nil {
|
||||
if _, err := stateMgr.Lock(t.Context(), statemgr.NewLockInfo()); err != nil {
|
||||
t.Fatalf("unexpected error locking state after cancelling apply: %s", err.Error())
|
||||
}
|
||||
}
|
||||
@@ -496,7 +496,7 @@ func TestCloud_applyWithCloudPlan(t *testing.T) {
|
||||
|
||||
stateMgr, _ := b.StateMgr(t.Context(), testBackendSingleWorkspaceName)
|
||||
// An error suggests that the state was not unlocked after apply
|
||||
if _, err := stateMgr.Lock(statemgr.NewLockInfo()); err != nil {
|
||||
if _, err := stateMgr.Lock(t.Context(), statemgr.NewLockInfo()); err != nil {
|
||||
t.Fatalf("unexpected error locking state after apply: %s", err.Error())
|
||||
}
|
||||
}
|
||||
@@ -644,7 +644,7 @@ func TestCloud_applyWithExclude(t *testing.T) {
|
||||
|
||||
stateMgr, _ := b.StateMgr(t.Context(), testBackendSingleWorkspaceName)
|
||||
// An error suggests that the state was not unlocked after apply
|
||||
if _, err := stateMgr.Lock(statemgr.NewLockInfo()); err != nil {
|
||||
if _, err := stateMgr.Lock(t.Context(), statemgr.NewLockInfo()); err != nil {
|
||||
t.Fatalf("unexpected error locking state after failed apply: %s", err.Error())
|
||||
}
|
||||
}
|
||||
@@ -744,7 +744,7 @@ func TestCloud_applyNoConfig(t *testing.T) {
|
||||
|
||||
stateMgr, _ := b.StateMgr(t.Context(), testBackendSingleWorkspaceName)
|
||||
// An error suggests that the state was not unlocked after apply
|
||||
if _, err := stateMgr.Lock(statemgr.NewLockInfo()); err != nil {
|
||||
if _, err := stateMgr.Lock(t.Context(), statemgr.NewLockInfo()); err != nil {
|
||||
t.Fatalf("unexpected error locking state after failed apply: %s", err.Error())
|
||||
}
|
||||
}
|
||||
@@ -1405,7 +1405,7 @@ func TestCloud_applyJSONWithProvisioner(t *testing.T) {
|
||||
|
||||
stateMgr, _ := b.StateMgr(t.Context(), testBackendSingleWorkspaceName)
|
||||
// An error suggests that the state was not unlocked after apply
|
||||
if _, err := stateMgr.Lock(statemgr.NewLockInfo()); err != nil {
|
||||
if _, err := stateMgr.Lock(t.Context(), statemgr.NewLockInfo()); err != nil {
|
||||
t.Fatalf("unexpected error locking state after apply: %s", err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,7 +64,7 @@ func (b *Cloud) LocalRun(ctx context.Context, op *backend.Operation) (*backend.L
|
||||
}()
|
||||
|
||||
log.Printf("[TRACE] cloud: reading remote state for workspace %q", remoteWorkspaceName)
|
||||
if err := stateMgr.RefreshState(); err != nil {
|
||||
if err := stateMgr.RefreshState(ctx); err != nil {
|
||||
diags = diags.Append(fmt.Errorf("error loading state: %w", err))
|
||||
return nil, nil, diags
|
||||
}
|
||||
|
||||
@@ -227,7 +227,7 @@ func TestRemoteContextWithVars(t *testing.T) {
|
||||
// When Context() returns an error, it should unlock the state,
|
||||
// so re-locking it is expected to succeed.
|
||||
stateMgr, _ := b.StateMgr(t.Context(), testBackendSingleWorkspaceName)
|
||||
if _, err := stateMgr.Lock(statemgr.NewLockInfo()); err != nil {
|
||||
if _, err := stateMgr.Lock(t.Context(), statemgr.NewLockInfo()); err != nil {
|
||||
t.Fatalf("unexpected error locking state: %s", err.Error())
|
||||
}
|
||||
} else {
|
||||
@@ -236,7 +236,7 @@ func TestRemoteContextWithVars(t *testing.T) {
|
||||
}
|
||||
// When Context() succeeds, this should fail w/ "workspace already locked"
|
||||
stateMgr, _ := b.StateMgr(t.Context(), testBackendSingleWorkspaceName)
|
||||
if _, err := stateMgr.Lock(statemgr.NewLockInfo()); err == nil {
|
||||
if _, err := stateMgr.Lock(t.Context(), statemgr.NewLockInfo()); err == nil {
|
||||
t.Fatal("unexpected success locking state after Context")
|
||||
}
|
||||
}
|
||||
@@ -444,7 +444,7 @@ func TestRemoteVariablesDoNotOverride(t *testing.T) {
|
||||
}
|
||||
// When Context() succeeds, this should fail w/ "workspace already locked"
|
||||
stateMgr, _ := b.StateMgr(t.Context(), testBackendSingleWorkspaceName)
|
||||
if _, err := stateMgr.Lock(statemgr.NewLockInfo()); err == nil {
|
||||
if _, err := stateMgr.Lock(t.Context(), statemgr.NewLockInfo()); err == nil {
|
||||
t.Fatal("unexpected success locking state after Context")
|
||||
}
|
||||
|
||||
|
||||
@@ -100,7 +100,7 @@ func TestCloud_planBasic(t *testing.T) {
|
||||
|
||||
stateMgr, _ := b.StateMgr(t.Context(), testBackendSingleWorkspaceName)
|
||||
// An error suggests that the state was not unlocked after the operation finished
|
||||
if _, err := stateMgr.Lock(statemgr.NewLockInfo()); err != nil {
|
||||
if _, err := stateMgr.Lock(t.Context(), statemgr.NewLockInfo()); err != nil {
|
||||
t.Fatalf("unexpected error locking state after successful plan: %s", err.Error())
|
||||
}
|
||||
}
|
||||
@@ -145,7 +145,7 @@ func TestCloud_planJSONBasic(t *testing.T) {
|
||||
|
||||
stateMgr, _ := b.StateMgr(t.Context(), testBackendSingleWorkspaceName)
|
||||
// An error suggests that the state was not unlocked after the operation finished
|
||||
if _, err := stateMgr.Lock(statemgr.NewLockInfo()); err != nil {
|
||||
if _, err := stateMgr.Lock(t.Context(), statemgr.NewLockInfo()); err != nil {
|
||||
t.Fatalf("unexpected error locking state after successful plan: %s", err.Error())
|
||||
}
|
||||
}
|
||||
@@ -174,7 +174,7 @@ func TestCloud_planCanceled(t *testing.T) {
|
||||
|
||||
stateMgr, _ := b.StateMgr(t.Context(), testBackendSingleWorkspaceName)
|
||||
// An error suggests that the state was not unlocked after the operation finished
|
||||
if _, err := stateMgr.Lock(statemgr.NewLockInfo()); err != nil {
|
||||
if _, err := stateMgr.Lock(t.Context(), statemgr.NewLockInfo()); err != nil {
|
||||
t.Fatalf("unexpected error locking state after cancelled plan: %s", err.Error())
|
||||
}
|
||||
}
|
||||
@@ -254,7 +254,7 @@ func TestCloud_planJSONFull(t *testing.T) {
|
||||
|
||||
stateMgr, _ := b.StateMgr(t.Context(), testBackendSingleWorkspaceName)
|
||||
// An error suggests that the state was not unlocked after the operation finished
|
||||
if _, err := stateMgr.Lock(statemgr.NewLockInfo()); err != nil {
|
||||
if _, err := stateMgr.Lock(t.Context(), statemgr.NewLockInfo()); err != nil {
|
||||
t.Fatalf("unexpected error locking state after successful plan: %s", err.Error())
|
||||
}
|
||||
}
|
||||
@@ -1322,7 +1322,7 @@ func TestCloud_planImportConfigGeneration(t *testing.T) {
|
||||
|
||||
stateMgr, _ := b.StateMgr(t.Context(), testBackendSingleWorkspaceName)
|
||||
// An error suggests that the state was not unlocked after the operation finished
|
||||
if _, err := stateMgr.Lock(statemgr.NewLockInfo()); err != nil {
|
||||
if _, err := stateMgr.Lock(t.Context(), statemgr.NewLockInfo()); err != nil {
|
||||
t.Fatalf("unexpected error locking state after successful plan: %s", err.Error())
|
||||
}
|
||||
|
||||
|
||||
@@ -78,7 +78,7 @@ func TestCloud_refreshBasicActuallyRunsApplyRefresh(t *testing.T) {
|
||||
|
||||
stateMgr, _ := b.StateMgr(t.Context(), testBackendSingleWorkspaceName)
|
||||
// An error suggests that the state was not unlocked after apply
|
||||
if _, err := stateMgr.Lock(statemgr.NewLockInfo()); err != nil {
|
||||
if _, err := stateMgr.Lock(t.Context(), statemgr.NewLockInfo()); err != nil {
|
||||
t.Fatalf("unexpected error locking state after apply: %s", err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -167,7 +167,11 @@ func (s *State) WriteState(state *states.State) error {
|
||||
}
|
||||
|
||||
// PersistState uploads a snapshot of the latest state as a StateVersion to Terraform Cloud
|
||||
func (s *State) PersistState(schemas *tofu.Schemas) error {
|
||||
func (s *State) PersistState(ctx context.Context, schemas *tofu.Schemas) error {
|
||||
// We want to be able to succeed in persisting state even when the
|
||||
// main context has been cancelled.
|
||||
ctx = context.WithoutCancel(ctx)
|
||||
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
|
||||
@@ -187,7 +191,7 @@ func (s *State) PersistState(schemas *tofu.Schemas) error {
|
||||
// We might be writing a new state altogether, but before we do that
|
||||
// we'll check to make sure there isn't already a snapshot present
|
||||
// that we ought to be updating.
|
||||
err := s.refreshState()
|
||||
err := s.refreshState(ctx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed checking for existing remote state: %w", err)
|
||||
}
|
||||
@@ -234,7 +238,7 @@ func (s *State) PersistState(schemas *tofu.Schemas) error {
|
||||
return fmt.Errorf("failed to marshal outputs to json: %w", err)
|
||||
}
|
||||
|
||||
err = s.uploadState(s.lineage, s.serial, s.forcePush, buf.Bytes(), jsonState, jsonStateOutputs)
|
||||
err = s.uploadState(ctx, s.lineage, s.serial, s.forcePush, buf.Bytes(), jsonState, jsonStateOutputs)
|
||||
if err != nil {
|
||||
s.stateUploadErr = true
|
||||
return fmt.Errorf("error uploading state: %w", err)
|
||||
@@ -298,8 +302,10 @@ func (s *State) uploadStateFallback(ctx context.Context, lineage string, serial
|
||||
return err
|
||||
}
|
||||
|
||||
func (s *State) uploadState(lineage string, serial uint64, isForcePush bool, state, jsonState, jsonStateOutputs []byte) error {
|
||||
ctx := context.Background()
|
||||
func (s *State) uploadState(ctx context.Context, lineage string, serial uint64, isForcePush bool, state, jsonState, jsonStateOutputs []byte) error {
|
||||
// Our request to write state should be allowed to run to completion
|
||||
// even if the overall context is cancelled.
|
||||
ctx = context.WithoutCancel(ctx)
|
||||
|
||||
options := tfe.StateVersionUploadOptions{
|
||||
StateVersionCreateOptions: tfe.StateVersionCreateOptions{
|
||||
@@ -337,14 +343,13 @@ func (s *State) uploadState(lineage string, serial uint64, isForcePush bool, sta
|
||||
}
|
||||
|
||||
// Lock calls the Client's Lock method if it's implemented.
|
||||
func (s *State) Lock(info *statemgr.LockInfo) (string, error) {
|
||||
func (s *State) Lock(ctx context.Context, info *statemgr.LockInfo) (string, error) {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
|
||||
if s.disableLocks {
|
||||
return "", nil
|
||||
}
|
||||
ctx := context.Background()
|
||||
|
||||
lockErr := &statemgr.LockError{Info: s.lockInfo}
|
||||
|
||||
@@ -367,17 +372,17 @@ func (s *State) Lock(info *statemgr.LockInfo) (string, error) {
|
||||
}
|
||||
|
||||
// statemgr.Refresher impl.
|
||||
func (s *State) RefreshState() error {
|
||||
func (s *State) RefreshState(ctx context.Context) error {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
return s.refreshState()
|
||||
return s.refreshState(ctx)
|
||||
}
|
||||
|
||||
// refreshState is the main implementation of RefreshState, but split out so
|
||||
// that we can make internal calls to it from methods that are already holding
|
||||
// the s.mu lock.
|
||||
func (s *State) refreshState() error {
|
||||
payload, err := s.getStatePayload()
|
||||
func (s *State) refreshState(ctx context.Context) error {
|
||||
payload, err := s.getStatePayload(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -407,8 +412,7 @@ func (s *State) refreshState() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *State) getStatePayload() (*remote.Payload, error) {
|
||||
ctx := context.Background()
|
||||
func (s *State) getStatePayload(ctx context.Context) (*remote.Payload, error) {
|
||||
|
||||
// Check the x-terraform-snapshot-interval header to see if it has a non-empty
|
||||
// value which would indicate snapshots are enabled
|
||||
@@ -443,7 +447,7 @@ func (s *State) getStatePayload() (*remote.Payload, error) {
|
||||
}
|
||||
|
||||
// Unlock calls the Client's Unlock method if it's implemented.
|
||||
func (s *State) Unlock(id string) error {
|
||||
func (s *State) Unlock(ctx context.Context, id string) error {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
|
||||
@@ -451,8 +455,6 @@ func (s *State) Unlock(id string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
// We first check if there was an error while uploading the latest
|
||||
// state. If so, we will not unlock the workspace to prevent any
|
||||
// changes from being applied until the correct state is uploaded.
|
||||
@@ -521,9 +523,7 @@ func (s *State) Delete(force bool) error {
|
||||
}
|
||||
|
||||
// GetRootOutputValues fetches output values from Terraform Cloud
|
||||
func (s *State) GetRootOutputValues() (map[string]*states.OutputValue, error) {
|
||||
ctx := context.Background()
|
||||
|
||||
func (s *State) GetRootOutputValues(ctx context.Context) (map[string]*states.OutputValue, error) {
|
||||
so, err := s.tfeClient.StateVersionOutputs.ReadCurrent(ctx, s.workspace.ID)
|
||||
|
||||
if err != nil {
|
||||
@@ -540,7 +540,7 @@ func (s *State) GetRootOutputValues() (map[string]*states.OutputValue, error) {
|
||||
// requires a higher level of authorization.
|
||||
log.Printf("[DEBUG] falling back to reading full state")
|
||||
|
||||
if err := s.RefreshState(); err != nil {
|
||||
if err := s.RefreshState(ctx); err != nil {
|
||||
return nil, fmt.Errorf("failed to load state: %w", err)
|
||||
}
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@ func TestState_GetRootOutputValues(t *testing.T) {
|
||||
state := &State{tfeClient: b.client, organization: b.organization, workspace: &tfe.Workspace{
|
||||
ID: "ws-abcd",
|
||||
}, encryption: encryption.StateEncryptionDisabled()}
|
||||
outputs, err := state.GetRootOutputValues()
|
||||
outputs, err := state.GetRootOutputValues(t.Context())
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("error returned from GetRootOutputValues: %s", err)
|
||||
@@ -119,11 +119,11 @@ func TestState(t *testing.T) {
|
||||
}
|
||||
}`)
|
||||
|
||||
if err := state.uploadState(state.lineage, state.serial, state.forcePush, data, jsonState, jsonStateOutputs); err != nil {
|
||||
if err := state.uploadState(t.Context(), state.lineage, state.serial, state.forcePush, data, jsonState, jsonStateOutputs); err != nil {
|
||||
t.Fatalf("put: %s", err)
|
||||
}
|
||||
|
||||
payload, err := state.getStatePayload()
|
||||
payload, err := state.getStatePayload(t.Context())
|
||||
if err != nil {
|
||||
t.Fatalf("get: %s", err)
|
||||
}
|
||||
@@ -135,7 +135,7 @@ func TestState(t *testing.T) {
|
||||
t.Fatalf("delete: %s", err)
|
||||
}
|
||||
|
||||
p, err := state.getStatePayload()
|
||||
p, err := state.getStatePayload(t.Context())
|
||||
if err != nil {
|
||||
t.Fatalf("get: %s", err)
|
||||
}
|
||||
@@ -175,25 +175,25 @@ func TestCloudLocks(t *testing.T) {
|
||||
infoB.Operation = "test"
|
||||
infoB.Who = "clientB"
|
||||
|
||||
lockIDA, err := lockerA.Lock(infoA)
|
||||
lockIDA, err := lockerA.Lock(t.Context(), infoA)
|
||||
if err != nil {
|
||||
t.Fatal("unable to get initial lock:", err)
|
||||
}
|
||||
|
||||
_, err = lockerB.Lock(infoB)
|
||||
_, err = lockerB.Lock(t.Context(), infoB)
|
||||
if err == nil {
|
||||
_ = lockerA.Unlock(lockIDA) // test already failed, no need to check err further
|
||||
_ = lockerA.Unlock(t.Context(), lockIDA) // test already failed, no need to check err further
|
||||
t.Fatal("client B obtained lock while held by client A")
|
||||
}
|
||||
if _, ok := err.(*statemgr.LockError); !ok {
|
||||
t.Errorf("expected a LockError, but was %t: %s", err, err)
|
||||
}
|
||||
|
||||
if err := lockerA.Unlock(lockIDA); err != nil {
|
||||
if err := lockerA.Unlock(t.Context(), lockIDA); err != nil {
|
||||
t.Fatal("error unlocking client A", err)
|
||||
}
|
||||
|
||||
lockIDB, err := lockerB.Lock(infoB)
|
||||
lockIDB, err := lockerB.Lock(t.Context(), infoB)
|
||||
if err != nil {
|
||||
t.Fatal("unable to obtain lock from client B")
|
||||
}
|
||||
@@ -202,7 +202,7 @@ func TestCloudLocks(t *testing.T) {
|
||||
t.Fatalf("duplicate lock IDs: %q", lockIDB)
|
||||
}
|
||||
|
||||
if err = lockerB.Unlock(lockIDB); err != nil {
|
||||
if err = lockerB.Unlock(t.Context(), lockIDB); err != nil {
|
||||
t.Fatal("error unlocking client B:", err)
|
||||
}
|
||||
}
|
||||
@@ -271,7 +271,7 @@ func TestState_PersistState(t *testing.T) {
|
||||
t.Fatal("expected nil initial readState")
|
||||
}
|
||||
|
||||
err := cloudState.PersistState(nil)
|
||||
err := cloudState.PersistState(t.Context(), nil)
|
||||
if err != nil {
|
||||
t.Fatalf("expected no error, got %q", err)
|
||||
}
|
||||
@@ -331,7 +331,7 @@ func TestState_PersistState(t *testing.T) {
|
||||
}
|
||||
cloudState.tfeClient = client
|
||||
|
||||
err = cloudState.RefreshState()
|
||||
err = cloudState.RefreshState(t.Context())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -345,7 +345,7 @@ func TestState_PersistState(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
err = cloudState.PersistState(nil)
|
||||
err = cloudState.PersistState(t.Context(), nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
@@ -443,7 +443,7 @@ func TestApply_defaultState(t *testing.T) {
|
||||
}
|
||||
|
||||
// create an existing state file
|
||||
if err := statemgr.WriteAndPersist(statemgr.NewFilesystem(statePath, encryption.StateEncryptionDisabled()), states.NewState(), nil); err != nil {
|
||||
if err := statemgr.WriteAndPersist(t.Context(), statemgr.NewFilesystem(statePath, encryption.StateEncryptionDisabled()), states.NewState(), nil); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
@@ -733,7 +733,7 @@ func TestApply_plan_backup(t *testing.T) {
|
||||
// create a state file that needs to be backed up
|
||||
fs := statemgr.NewFilesystem(statePath, encryption.StateEncryptionDisabled())
|
||||
fs.StateSnapshotMeta()
|
||||
if err := statemgr.WriteAndPersist(fs, states.NewState(), nil); err != nil {
|
||||
if err := statemgr.WriteAndPersist(t.Context(), fs, states.NewState(), nil); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ package clistate
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
@@ -48,6 +49,13 @@ type LocalState struct {
|
||||
written bool
|
||||
}
|
||||
|
||||
// LocalState is not really a "state manager" -- this is a holdover from long
|
||||
// ago where .terraform/terraform.tfstate was actually a state snapshot rather
|
||||
// than just some metadata about the initialized backend configuration -- but
|
||||
// various bits of supporting code assume that it implements the same
|
||||
// locking API that real state managers do.
|
||||
var _ statemgr.Locker = (*LocalState)(nil)
|
||||
|
||||
// SetState will force a specific state in-memory for this local state.
|
||||
func (s *LocalState) SetState(state *tofu.State) {
|
||||
s.mu.Lock()
|
||||
@@ -187,7 +195,7 @@ func (s *LocalState) RefreshState() error {
|
||||
}
|
||||
|
||||
// Lock implements a local filesystem state.Locker.
|
||||
func (s *LocalState) Lock(info *statemgr.LockInfo) (string, error) {
|
||||
func (s *LocalState) Lock(_ context.Context, info *statemgr.LockInfo) (string, error) {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
|
||||
@@ -219,7 +227,7 @@ func (s *LocalState) Lock(info *statemgr.LockInfo) (string, error) {
|
||||
return s.lockID, s.writeLockInfo(info)
|
||||
}
|
||||
|
||||
func (s *LocalState) Unlock(id string) error {
|
||||
func (s *LocalState) Unlock(_ context.Context, id string) error {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
|
||||
|
||||
@@ -150,7 +150,7 @@ func (l *locker) Unlock() tfdiags.Diagnostics {
|
||||
}
|
||||
|
||||
err := slowmessage.Do(LockThreshold, func() error {
|
||||
return l.state.Unlock(l.lockID)
|
||||
return l.state.Unlock(context.TODO(), l.lockID)
|
||||
}, l.view.Unlocking)
|
||||
|
||||
if err != nil {
|
||||
|
||||
@@ -281,7 +281,7 @@ func (c *ImportCommand) Run(args []string) int {
|
||||
c.Ui.Error(fmt.Sprintf("Error writing state file: %s", err))
|
||||
return 1
|
||||
}
|
||||
if err := state.PersistState(schemas); err != nil {
|
||||
if err := state.PersistState(ctx, schemas); err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Error writing state file: %s", err))
|
||||
return 1
|
||||
}
|
||||
|
||||
@@ -262,7 +262,7 @@ func (c *InitCommand) Run(args []string) int {
|
||||
return 1
|
||||
}
|
||||
|
||||
if err := sMgr.RefreshState(); err != nil {
|
||||
if err := sMgr.RefreshState(ctx); err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Error refreshing state: %s", err))
|
||||
return 1
|
||||
}
|
||||
|
||||
@@ -1257,7 +1257,7 @@ func TestInit_inputFalse(t *testing.T) {
|
||||
"",
|
||||
)
|
||||
})
|
||||
if err := statemgr.WriteAndPersist(statemgr.NewFilesystem("foo", encryption.StateEncryptionDisabled()), fooState, nil); err != nil {
|
||||
if err := statemgr.WriteAndPersist(t.Context(), statemgr.NewFilesystem("foo", encryption.StateEncryptionDisabled()), fooState, nil); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
barState := states.BuildState(func(s *states.SyncState) {
|
||||
@@ -1268,7 +1268,7 @@ func TestInit_inputFalse(t *testing.T) {
|
||||
"",
|
||||
)
|
||||
})
|
||||
if err := statemgr.WriteAndPersist(statemgr.NewFilesystem("bar", encryption.StateEncryptionDisabled()), barState, nil); err != nil {
|
||||
if err := statemgr.WriteAndPersist(t.Context(), statemgr.NewFilesystem("bar", encryption.StateEncryptionDisabled()), barState, nil); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
|
||||
@@ -989,7 +989,7 @@ func (m *Meta) backend_C_r_s(ctx context.Context, c *configs.Backend, cHash int,
|
||||
diags = diags.Append(fmt.Errorf(errBackendLocalRead, err))
|
||||
return nil, diags
|
||||
}
|
||||
if err := localState.RefreshState(); err != nil {
|
||||
if err := localState.RefreshState(ctx); err != nil {
|
||||
diags = diags.Append(fmt.Errorf(errBackendLocalRead, err))
|
||||
return nil, diags
|
||||
}
|
||||
@@ -1052,7 +1052,7 @@ func (m *Meta) backend_C_r_s(ctx context.Context, c *configs.Backend, cHash int,
|
||||
diags = diags.Append(fmt.Errorf(errBackendMigrateLocalDelete, err))
|
||||
return nil, diags
|
||||
}
|
||||
if err := localState.PersistState(nil); err != nil {
|
||||
if err := localState.PersistState(ctx, nil); err != nil {
|
||||
diags = diags.Append(fmt.Errorf(errBackendMigrateLocalDelete, err))
|
||||
return nil, diags
|
||||
}
|
||||
|
||||
@@ -270,7 +270,7 @@ func (m *Meta) backendMigrateState_s_s(ctx context.Context, opts *backendMigrate
|
||||
return fmt.Errorf(strings.TrimSpace(
|
||||
errMigrateSingleLoadDefault), opts.SourceType, err)
|
||||
}
|
||||
if err := sourceState.RefreshState(); err != nil {
|
||||
if err := sourceState.RefreshState(ctx); err != nil {
|
||||
return fmt.Errorf(strings.TrimSpace(
|
||||
errMigrateSingleLoadDefault), opts.SourceType, err)
|
||||
}
|
||||
@@ -318,7 +318,7 @@ func (m *Meta) backendMigrateState_s_s(ctx context.Context, opts *backendMigrate
|
||||
return fmt.Errorf(strings.TrimSpace(
|
||||
errMigrateSingleLoadDefault), opts.DestinationType, err)
|
||||
}
|
||||
if err := destinationState.RefreshState(); err != nil {
|
||||
if err := destinationState.RefreshState(ctx); err != nil {
|
||||
return fmt.Errorf(strings.TrimSpace(
|
||||
errMigrateSingleLoadDefault), opts.DestinationType, err)
|
||||
}
|
||||
@@ -371,12 +371,12 @@ func (m *Meta) backendMigrateState_s_s(ctx context.Context, opts *backendMigrate
|
||||
// We now own a lock, so double check that we have the version
|
||||
// corresponding to the lock.
|
||||
log.Print("[TRACE] backendMigrateState: refreshing source workspace state")
|
||||
if err := sourceState.RefreshState(); err != nil {
|
||||
if err := sourceState.RefreshState(ctx); err != nil {
|
||||
return fmt.Errorf(strings.TrimSpace(
|
||||
errMigrateSingleLoadDefault), opts.SourceType, err)
|
||||
}
|
||||
log.Print("[TRACE] backendMigrateState: refreshing destination workspace state")
|
||||
if err := destinationState.RefreshState(); err != nil {
|
||||
if err := destinationState.RefreshState(ctx); err != nil {
|
||||
return fmt.Errorf(strings.TrimSpace(
|
||||
errMigrateSingleLoadDefault), opts.SourceType, err)
|
||||
}
|
||||
@@ -455,7 +455,7 @@ func (m *Meta) backendMigrateState_s_s(ctx context.Context, opts *backendMigrate
|
||||
// so requiring schemas here could lead to a catch-22 where it requires some manual
|
||||
// intervention to proceed far enough for provider installation. To avoid this,
|
||||
// when migrating to TFC backend, the initial JSON variant of state won't be generated and stored.
|
||||
if err := destinationState.PersistState(nil); err != nil {
|
||||
if err := destinationState.PersistState(ctx, nil); err != nil {
|
||||
return fmt.Errorf(strings.TrimSpace(errBackendStateCopy),
|
||||
opts.SourceType, opts.DestinationType, err)
|
||||
}
|
||||
@@ -500,7 +500,7 @@ func (m *Meta) backendMigrateNonEmptyConfirm(
|
||||
|
||||
// Helper to write the state
|
||||
saveHelper := func(n, path string, s *states.State) error {
|
||||
return statemgr.WriteAndPersist(statemgr.NewFilesystem(path, encryption.StateEncryptionDisabled()), s, nil)
|
||||
return statemgr.WriteAndPersist(context.TODO(), statemgr.NewFilesystem(path, encryption.StateEncryptionDisabled()), s, nil)
|
||||
}
|
||||
|
||||
// Write the states
|
||||
@@ -602,7 +602,7 @@ func (m *Meta) backendMigrateTFC(ctx context.Context, opts *backendMigrateOpts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := sourceState.RefreshState(); err != nil {
|
||||
if err := sourceState.RefreshState(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
if sourceState.State().Empty() {
|
||||
@@ -690,7 +690,7 @@ func (m *Meta) backendMigrateState_S_TFC(ctx context.Context, opts *backendMigra
|
||||
errMigrateSingleLoadDefault), opts.SourceType, err)
|
||||
}
|
||||
// RefreshState is what actually pulls the state to be evaluated.
|
||||
if err := sourceState.RefreshState(); err != nil {
|
||||
if err := sourceState.RefreshState(ctx); err != nil {
|
||||
return fmt.Errorf(strings.TrimSpace(
|
||||
errMigrateSingleLoadDefault), opts.SourceType, err)
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@ func TestMetaBackend_emptyDir(t *testing.T) {
|
||||
if err := s.WriteState(testState()); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := s.PersistState(nil); err != nil {
|
||||
if err := s.PersistState(t.Context(), nil); err != nil {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
|
||||
@@ -123,7 +123,7 @@ func TestMetaBackend_emptyWithDefaultState(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
if err := s.RefreshState(); err != nil {
|
||||
if err := s.RefreshState(t.Context()); err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
if actual := s.State().String(); actual != testState().String() {
|
||||
@@ -146,7 +146,7 @@ func TestMetaBackend_emptyWithDefaultState(t *testing.T) {
|
||||
if err := s.WriteState(next); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := s.PersistState(nil); err != nil {
|
||||
if err := s.PersistState(t.Context(), nil); err != nil {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
|
||||
@@ -194,7 +194,7 @@ func TestMetaBackend_emptyWithExplicitState(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
if err := s.RefreshState(); err != nil {
|
||||
if err := s.RefreshState(t.Context()); err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
if actual := s.State().String(); actual != testState().String() {
|
||||
@@ -217,7 +217,7 @@ func TestMetaBackend_emptyWithExplicitState(t *testing.T) {
|
||||
if err := s.WriteState(next); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := s.PersistState(nil); err != nil {
|
||||
if err := s.PersistState(t.Context(), nil); err != nil {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
|
||||
@@ -264,7 +264,7 @@ func TestMetaBackend_configureNew(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
if err := s.RefreshState(); err != nil {
|
||||
if err := s.RefreshState(t.Context()); err != nil {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
state := s.State()
|
||||
@@ -279,7 +279,7 @@ func TestMetaBackend_configureNew(t *testing.T) {
|
||||
if err := s.WriteState(state); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := s.PersistState(nil); err != nil {
|
||||
if err := s.PersistState(t.Context(), nil); err != nil {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
|
||||
@@ -337,7 +337,7 @@ func TestMetaBackend_configureNewWithState(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
state, err := statemgr.RefreshAndRead(s)
|
||||
state, err := statemgr.RefreshAndRead(t.Context(), s)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
@@ -353,7 +353,7 @@ func TestMetaBackend_configureNewWithState(t *testing.T) {
|
||||
state = states.NewState()
|
||||
mark := markStateForMatching(state, "changing")
|
||||
|
||||
if err := statemgr.WriteAndPersist(s, state, nil); err != nil {
|
||||
if err := statemgr.WriteAndPersist(t.Context(), s, state, nil); err != nil {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
|
||||
@@ -460,7 +460,7 @@ func TestMetaBackend_configureNewWithStateNoMigrate(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
if err := s.RefreshState(); err != nil {
|
||||
if err := s.RefreshState(t.Context()); err != nil {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
if state := s.State(); state != nil {
|
||||
@@ -503,7 +503,7 @@ func TestMetaBackend_configureNewWithStateExisting(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
if err := s.RefreshState(); err != nil {
|
||||
if err := s.RefreshState(t.Context()); err != nil {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
state := s.State()
|
||||
@@ -521,7 +521,7 @@ func TestMetaBackend_configureNewWithStateExisting(t *testing.T) {
|
||||
if err := s.WriteState(state); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := s.PersistState(nil); err != nil {
|
||||
if err := s.PersistState(t.Context(), nil); err != nil {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
|
||||
@@ -577,7 +577,7 @@ func TestMetaBackend_configureNewWithStateExistingNoMigrate(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
if err := s.RefreshState(); err != nil {
|
||||
if err := s.RefreshState(t.Context()); err != nil {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
state := s.State()
|
||||
@@ -594,7 +594,7 @@ func TestMetaBackend_configureNewWithStateExistingNoMigrate(t *testing.T) {
|
||||
if err := s.WriteState(state); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := s.PersistState(nil); err != nil {
|
||||
if err := s.PersistState(t.Context(), nil); err != nil {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
|
||||
@@ -644,7 +644,7 @@ func TestMetaBackend_configuredUnchanged(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
if err := s.RefreshState(); err != nil {
|
||||
if err := s.RefreshState(t.Context()); err != nil {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
state := s.State()
|
||||
@@ -788,7 +788,7 @@ func TestMetaBackend_configuredUnchangedWithStaticEvalVars(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
if err := s.RefreshState(); err != nil {
|
||||
if err := s.RefreshState(t.Context()); err != nil {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
state := s.State()
|
||||
@@ -834,7 +834,7 @@ func TestMetaBackend_configuredChange(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
if err := s.RefreshState(); err != nil {
|
||||
if err := s.RefreshState(t.Context()); err != nil {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
state := s.State()
|
||||
@@ -859,7 +859,7 @@ func TestMetaBackend_configuredChange(t *testing.T) {
|
||||
if err := s.WriteState(state); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := s.PersistState(nil); err != nil {
|
||||
if err := s.PersistState(t.Context(), nil); err != nil {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
|
||||
@@ -922,7 +922,7 @@ func TestMetaBackend_reconfigureChange(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
if err := s.RefreshState(); err != nil {
|
||||
if err := s.RefreshState(t.Context()); err != nil {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
newState := s.State()
|
||||
@@ -932,7 +932,7 @@ func TestMetaBackend_reconfigureChange(t *testing.T) {
|
||||
|
||||
// verify that the old state is still there
|
||||
s = statemgr.NewFilesystem("local-state.tfstate", encryption.StateEncryptionDisabled())
|
||||
if err := s.RefreshState(); err != nil {
|
||||
if err := s.RefreshState(t.Context()); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
oldState := s.State()
|
||||
@@ -1062,7 +1062,7 @@ func TestMetaBackend_configuredChangeCopy(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
if err := s.RefreshState(); err != nil {
|
||||
if err := s.RefreshState(t.Context()); err != nil {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
state := s.State()
|
||||
@@ -1115,7 +1115,7 @@ func TestMetaBackend_configuredChangeCopy_singleState(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
if err := s.RefreshState(); err != nil {
|
||||
if err := s.RefreshState(t.Context()); err != nil {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
state := s.State()
|
||||
@@ -1169,7 +1169,7 @@ func TestMetaBackend_configuredChangeCopy_multiToSingleDefault(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
if err := s.RefreshState(); err != nil {
|
||||
if err := s.RefreshState(t.Context()); err != nil {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
state := s.State()
|
||||
@@ -1223,7 +1223,7 @@ func TestMetaBackend_configuredChangeCopy_multiToSingle(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
if err := s.RefreshState(); err != nil {
|
||||
if err := s.RefreshState(t.Context()); err != nil {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
state := s.State()
|
||||
@@ -1297,7 +1297,7 @@ func TestMetaBackend_configuredChangeCopy_multiToSingleCurrentEnv(t *testing.T)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
if err := s.RefreshState(); err != nil {
|
||||
if err := s.RefreshState(t.Context()); err != nil {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
state := s.State()
|
||||
@@ -1365,7 +1365,7 @@ func TestMetaBackend_configuredChangeCopy_multiToMulti(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
if err := s.RefreshState(); err != nil {
|
||||
if err := s.RefreshState(t.Context()); err != nil {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
state := s.State()
|
||||
@@ -1383,7 +1383,7 @@ func TestMetaBackend_configuredChangeCopy_multiToMulti(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
if err := s.RefreshState(); err != nil {
|
||||
if err := s.RefreshState(t.Context()); err != nil {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
state := s.State()
|
||||
@@ -1463,7 +1463,7 @@ func TestMetaBackend_configuredChangeCopy_multiToNoDefaultWithDefault(t *testing
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
if err := s.RefreshState(); err != nil {
|
||||
if err := s.RefreshState(t.Context()); err != nil {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
state := s.State()
|
||||
@@ -1537,7 +1537,7 @@ func TestMetaBackend_configuredChangeCopy_multiToNoDefaultWithoutDefault(t *test
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
if err := s.RefreshState(); err != nil {
|
||||
if err := s.RefreshState(t.Context()); err != nil {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
state := s.State()
|
||||
@@ -1590,7 +1590,7 @@ func TestMetaBackend_configuredUnset(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
if err := s.RefreshState(); err != nil {
|
||||
if err := s.RefreshState(t.Context()); err != nil {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
state := s.State()
|
||||
@@ -1614,7 +1614,7 @@ func TestMetaBackend_configuredUnset(t *testing.T) {
|
||||
if err := s.WriteState(testState()); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := s.PersistState(nil); err != nil {
|
||||
if err := s.PersistState(t.Context(), nil); err != nil {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
|
||||
@@ -1654,7 +1654,7 @@ func TestMetaBackend_configuredUnsetCopy(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
if err := s.RefreshState(); err != nil {
|
||||
if err := s.RefreshState(t.Context()); err != nil {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
state := s.State()
|
||||
@@ -1674,7 +1674,7 @@ func TestMetaBackend_configuredUnsetCopy(t *testing.T) {
|
||||
if err := s.WriteState(testState()); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := s.PersistState(nil); err != nil {
|
||||
if err := s.PersistState(t.Context(), nil); err != nil {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
|
||||
@@ -1724,7 +1724,7 @@ func TestMetaBackend_planLocal(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
if err := s.RefreshState(); err != nil {
|
||||
if err := s.RefreshState(t.Context()); err != nil {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
state := s.State()
|
||||
@@ -1755,7 +1755,7 @@ func TestMetaBackend_planLocal(t *testing.T) {
|
||||
if err := s.WriteState(state); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := s.PersistState(nil); err != nil {
|
||||
if err := s.PersistState(t.Context(), nil); err != nil {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
|
||||
@@ -1807,7 +1807,7 @@ func TestMetaBackend_planLocalStatePath(t *testing.T) {
|
||||
statePath := "foo.tfstate"
|
||||
|
||||
// put an initial state there that needs to be backed up
|
||||
err = statemgr.WriteAndPersist(statemgr.NewFilesystem(statePath, encryption.StateEncryptionDisabled()), original, nil)
|
||||
err = statemgr.WriteAndPersist(t.Context(), statemgr.NewFilesystem(statePath, encryption.StateEncryptionDisabled()), original, nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -1827,7 +1827,7 @@ func TestMetaBackend_planLocalStatePath(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
if err := s.RefreshState(); err != nil {
|
||||
if err := s.RefreshState(t.Context()); err != nil {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
state := s.State()
|
||||
@@ -1858,7 +1858,7 @@ func TestMetaBackend_planLocalStatePath(t *testing.T) {
|
||||
if err := s.WriteState(state); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := s.PersistState(nil); err != nil {
|
||||
if err := s.PersistState(t.Context(), nil); err != nil {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
|
||||
@@ -1918,7 +1918,7 @@ func TestMetaBackend_planLocalMatch(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
if err := s.RefreshState(); err != nil {
|
||||
if err := s.RefreshState(t.Context()); err != nil {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
state := s.State()
|
||||
@@ -1947,7 +1947,7 @@ func TestMetaBackend_planLocalMatch(t *testing.T) {
|
||||
if err := s.WriteState(state); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := s.PersistState(nil); err != nil {
|
||||
if err := s.PersistState(t.Context(), nil); err != nil {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
|
||||
|
||||
@@ -103,7 +103,7 @@ func (c *OutputCommand) Outputs(ctx context.Context, statePath string, enc encry
|
||||
return nil, diags
|
||||
}
|
||||
|
||||
output, err := stateStore.GetRootOutputValues()
|
||||
output, err := stateStore.GetRootOutputValues(ctx)
|
||||
if err != nil {
|
||||
return nil, diags.Append(err)
|
||||
}
|
||||
|
||||
@@ -117,7 +117,7 @@ func (c *ProvidersCommand) Run(args []string) int {
|
||||
c.Ui.Error(fmt.Sprintf("Failed to load state: %s", err))
|
||||
return 1
|
||||
}
|
||||
if err := s.RefreshState(); err != nil {
|
||||
if err := s.RefreshState(ctx); err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Failed to load state: %s", err))
|
||||
return 1
|
||||
}
|
||||
|
||||
@@ -238,7 +238,7 @@ func TestRefresh_defaultState(t *testing.T) {
|
||||
statePath := testStateFile(t, originalState)
|
||||
|
||||
localState := statemgr.NewFilesystem(statePath, encryption.StateEncryptionDisabled())
|
||||
if err := localState.RefreshState(); err != nil {
|
||||
if err := localState.RefreshState(t.Context()); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
s := localState.State()
|
||||
|
||||
@@ -521,7 +521,7 @@ func getStateFromBackend(ctx context.Context, b backend.Backend, workspace strin
|
||||
}
|
||||
|
||||
// Refresh the state store with the latest state snapshot from persistent storage
|
||||
if err := stateStore.RefreshState(); err != nil {
|
||||
if err := stateStore.RefreshState(ctx); err != nil {
|
||||
tracing.SetSpanError(span, err)
|
||||
return nil, fmt.Errorf("failed to load state: %w", err)
|
||||
}
|
||||
|
||||
@@ -70,7 +70,7 @@ func (c *StateListCommand) Run(args []string) int {
|
||||
c.Ui.Error(fmt.Sprintf(errStateLoadingState, err))
|
||||
return 1
|
||||
}
|
||||
if err := stateMgr.RefreshState(); err != nil {
|
||||
if err := stateMgr.RefreshState(ctx); err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Failed to load state: %s", err))
|
||||
return 1
|
||||
}
|
||||
|
||||
@@ -120,7 +120,7 @@ func (c *StateMvCommand) Run(args []string) int {
|
||||
}()
|
||||
}
|
||||
|
||||
if err := stateFromMgr.RefreshState(); err != nil {
|
||||
if err := stateFromMgr.RefreshState(ctx); err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Failed to refresh source state: %s", err))
|
||||
return 1
|
||||
}
|
||||
@@ -158,7 +158,7 @@ func (c *StateMvCommand) Run(args []string) int {
|
||||
}()
|
||||
}
|
||||
|
||||
if err := stateToMgr.RefreshState(); err != nil {
|
||||
if err := stateToMgr.RefreshState(ctx); err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Failed to refresh destination state: %s", err))
|
||||
return 1
|
||||
}
|
||||
@@ -420,7 +420,7 @@ func (c *StateMvCommand) Run(args []string) int {
|
||||
c.Ui.Error(fmt.Sprintf(errStateRmPersist, err))
|
||||
return 1
|
||||
}
|
||||
if err := stateToMgr.PersistState(schemas); err != nil {
|
||||
if err := stateToMgr.PersistState(ctx, schemas); err != nil {
|
||||
c.Ui.Error(fmt.Sprintf(errStateRmPersist, err))
|
||||
return 1
|
||||
}
|
||||
@@ -431,7 +431,7 @@ func (c *StateMvCommand) Run(args []string) int {
|
||||
c.Ui.Error(fmt.Sprintf(errStateRmPersist, err))
|
||||
return 1
|
||||
}
|
||||
if err := stateFromMgr.PersistState(schemas); err != nil {
|
||||
if err := stateFromMgr.PersistState(ctx, schemas); err != nil {
|
||||
c.Ui.Error(fmt.Sprintf(errStateRmPersist, err))
|
||||
return 1
|
||||
}
|
||||
|
||||
@@ -65,7 +65,7 @@ func (c *StatePullCommand) Run(args []string) int {
|
||||
c.Ui.Error(fmt.Sprintf(errStateLoadingState, err))
|
||||
return 1
|
||||
}
|
||||
if err := stateMgr.RefreshState(); err != nil {
|
||||
if err := stateMgr.RefreshState(ctx); err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Failed to refresh state: %s", err))
|
||||
return 1
|
||||
}
|
||||
|
||||
@@ -128,7 +128,7 @@ func (c *StatePushCommand) Run(args []string) int {
|
||||
}()
|
||||
}
|
||||
|
||||
if err := stateMgr.RefreshState(); err != nil {
|
||||
if err := stateMgr.RefreshState(ctx); err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Failed to refresh destination state: %s", err))
|
||||
return 1
|
||||
}
|
||||
@@ -155,7 +155,7 @@ func (c *StatePushCommand) Run(args []string) int {
|
||||
c.Ui.Error(fmt.Sprintf("Failed to write state: %s", err))
|
||||
return 1
|
||||
}
|
||||
if err := stateMgr.PersistState(schemas); err != nil {
|
||||
if err := stateMgr.PersistState(ctx, schemas); err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Failed to persist state: %s", err))
|
||||
return 1
|
||||
}
|
||||
|
||||
@@ -273,7 +273,7 @@ func TestStatePush_forceRemoteState(t *testing.T) {
|
||||
if err := sMgr.WriteState(states.NewState()); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := sMgr.PersistState(nil); err != nil {
|
||||
if err := sMgr.PersistState(t.Context(), nil); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
|
||||
@@ -110,7 +110,7 @@ func (c *StateReplaceProviderCommand) Run(args []string) int {
|
||||
}
|
||||
|
||||
// Refresh and load state
|
||||
if err := stateMgr.RefreshState(); err != nil {
|
||||
if err := stateMgr.RefreshState(ctx); err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Failed to refresh source state: %s", err))
|
||||
return 1
|
||||
}
|
||||
@@ -197,7 +197,7 @@ func (c *StateReplaceProviderCommand) Run(args []string) int {
|
||||
c.Ui.Error(fmt.Sprintf(errStateRmPersist, err))
|
||||
return 1
|
||||
}
|
||||
if err := stateMgr.PersistState(schemas); err != nil {
|
||||
if err := stateMgr.PersistState(ctx, schemas); err != nil {
|
||||
c.Ui.Error(fmt.Sprintf(errStateRmPersist, err))
|
||||
return 1
|
||||
}
|
||||
|
||||
@@ -77,7 +77,7 @@ func (c *StateRmCommand) Run(args []string) int {
|
||||
}()
|
||||
}
|
||||
|
||||
if err := stateMgr.RefreshState(); err != nil {
|
||||
if err := stateMgr.RefreshState(ctx); err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Failed to refresh state: %s", err))
|
||||
return 1
|
||||
}
|
||||
@@ -144,7 +144,7 @@ func (c *StateRmCommand) Run(args []string) int {
|
||||
c.Ui.Error(fmt.Sprintf(errStateRmPersist, err))
|
||||
return 1
|
||||
}
|
||||
if err := stateMgr.PersistState(schemas); err != nil {
|
||||
if err := stateMgr.PersistState(ctx, schemas); err != nil {
|
||||
c.Ui.Error(fmt.Sprintf(errStateRmPersist, err))
|
||||
return 1
|
||||
}
|
||||
|
||||
@@ -138,7 +138,7 @@ func (c *StateShowCommand) Run(args []string) int {
|
||||
c.Streams.Eprintln(fmt.Sprintf(errStateLoadingState, err))
|
||||
return 1
|
||||
}
|
||||
if err := stateMgr.RefreshState(); err != nil {
|
||||
if err := stateMgr.RefreshState(ctx); err != nil {
|
||||
c.Streams.Eprintf("Failed to refresh state: %s\n", err)
|
||||
return 1
|
||||
}
|
||||
|
||||
@@ -118,7 +118,7 @@ func (c *TaintCommand) Run(args []string) int {
|
||||
}()
|
||||
}
|
||||
|
||||
if err := stateMgr.RefreshState(); err != nil {
|
||||
if err := stateMgr.RefreshState(ctx); err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Failed to load state: %s", err))
|
||||
return 1
|
||||
}
|
||||
@@ -193,7 +193,7 @@ func (c *TaintCommand) Run(args []string) int {
|
||||
c.Ui.Error(fmt.Sprintf("Error writing state file: %s", err))
|
||||
return 1
|
||||
}
|
||||
if err := stateMgr.PersistState(schemas); err != nil {
|
||||
if err := stateMgr.PersistState(ctx, schemas); err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Error writing state file: %s", err))
|
||||
return 1
|
||||
}
|
||||
|
||||
@@ -132,7 +132,7 @@ func (c *UnlockCommand) Run(args []string) int {
|
||||
}
|
||||
}
|
||||
|
||||
if err := stateMgr.Unlock(lockID); err != nil {
|
||||
if err := stateMgr.Unlock(ctx, lockID); err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Failed to unlock state: %s", err))
|
||||
return 1
|
||||
}
|
||||
|
||||
@@ -109,7 +109,7 @@ func (c *UntaintCommand) Run(args []string) int {
|
||||
}()
|
||||
}
|
||||
|
||||
if err := stateMgr.RefreshState(); err != nil {
|
||||
if err := stateMgr.RefreshState(ctx); err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Failed to load state: %s", err))
|
||||
return 1
|
||||
}
|
||||
@@ -194,7 +194,7 @@ func (c *UntaintCommand) Run(args []string) int {
|
||||
c.Ui.Error(fmt.Sprintf("Error writing state file: %s", err))
|
||||
return 1
|
||||
}
|
||||
if err := stateMgr.PersistState(schemas); err != nil {
|
||||
if err := stateMgr.PersistState(ctx, schemas); err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Error writing state file: %s", err))
|
||||
return 1
|
||||
}
|
||||
|
||||
@@ -252,7 +252,7 @@ func TestWorkspace_createWithState(t *testing.T) {
|
||||
)
|
||||
})
|
||||
|
||||
err := statemgr.WriteAndPersist(statemgr.NewFilesystem("test.tfstate", encryption.StateEncryptionDisabled()), originalState, nil)
|
||||
err := statemgr.WriteAndPersist(t.Context(), statemgr.NewFilesystem("test.tfstate", encryption.StateEncryptionDisabled()), originalState, nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -270,7 +270,7 @@ func TestWorkspace_createWithState(t *testing.T) {
|
||||
|
||||
newPath := filepath.Join(local.DefaultWorkspaceDir, "test", DefaultStateFilename)
|
||||
envState := statemgr.NewFilesystem(newPath, encryption.StateEncryptionDisabled())
|
||||
err = envState.RefreshState()
|
||||
err = envState.RefreshState(t.Context())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
@@ -134,7 +134,7 @@ func (c *WorkspaceDeleteCommand) Run(args []string) int {
|
||||
stateLocker = clistate.NewNoopLocker()
|
||||
}
|
||||
|
||||
if err := stateMgr.RefreshState(); err != nil {
|
||||
if err := stateMgr.RefreshState(ctx); err != nil {
|
||||
// We need to release the lock before exit
|
||||
stateLocker.Unlock()
|
||||
c.Ui.Error(err.Error())
|
||||
|
||||
@@ -173,7 +173,7 @@ func (c *WorkspaceNewCommand) Run(args []string) int {
|
||||
c.Ui.Error(err.Error())
|
||||
return 1
|
||||
}
|
||||
err = stateMgr.PersistState(nil)
|
||||
err = stateMgr.PersistState(ctx, nil)
|
||||
if err != nil {
|
||||
c.Ui.Error(err.Error())
|
||||
return 1
|
||||
|
||||
@@ -15,7 +15,7 @@ func TestRemoteClient_noPayload(t *testing.T) {
|
||||
s := &State{
|
||||
Client: nilClient{},
|
||||
}
|
||||
if err := s.RefreshState(); err != nil {
|
||||
if err := s.RefreshState(t.Context()); err != nil {
|
||||
t.Fatal("error refreshing empty remote state")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ package remote
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
"sync"
|
||||
@@ -77,8 +78,8 @@ func (s *State) State() *states.State {
|
||||
return s.state.DeepCopy()
|
||||
}
|
||||
|
||||
func (s *State) GetRootOutputValues() (map[string]*states.OutputValue, error) {
|
||||
if err := s.RefreshState(); err != nil {
|
||||
func (s *State) GetRootOutputValues(ctx context.Context) (map[string]*states.OutputValue, error) {
|
||||
if err := s.RefreshState(ctx); err != nil {
|
||||
return nil, fmt.Errorf("Failed to load state: %w", err)
|
||||
}
|
||||
|
||||
@@ -142,7 +143,7 @@ func (s *State) WriteStateForMigration(f *statefile.File, force bool) error {
|
||||
}
|
||||
|
||||
// statemgr.Refresher impl.
|
||||
func (s *State) RefreshState() error {
|
||||
func (s *State) RefreshState(_ context.Context) error {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
return s.refreshState()
|
||||
@@ -184,7 +185,7 @@ func (s *State) refreshState() error {
|
||||
}
|
||||
|
||||
// statemgr.Persister impl.
|
||||
func (s *State) PersistState(schemas *tofu.Schemas) error {
|
||||
func (s *State) PersistState(_ context.Context, schemas *tofu.Schemas) error {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
|
||||
@@ -255,7 +256,7 @@ func (s *State) ShouldPersistIntermediateState(info *local.IntermediateStatePers
|
||||
}
|
||||
|
||||
// Lock calls the Client's Lock method if it's implemented.
|
||||
func (s *State) Lock(info *statemgr.LockInfo) (string, error) {
|
||||
func (s *State) Lock(ctx context.Context, info *statemgr.LockInfo) (string, error) {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
|
||||
@@ -264,13 +265,13 @@ func (s *State) Lock(info *statemgr.LockInfo) (string, error) {
|
||||
}
|
||||
|
||||
if c, ok := s.Client.(ClientLocker); ok {
|
||||
return c.Lock(info)
|
||||
return c.Lock(ctx, info)
|
||||
}
|
||||
return "", nil
|
||||
}
|
||||
|
||||
// Unlock calls the Client's Unlock method if it's implemented.
|
||||
func (s *State) Unlock(id string) error {
|
||||
func (s *State) Unlock(ctx context.Context, id string) error {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
|
||||
@@ -279,7 +280,7 @@ func (s *State) Unlock(id string) error {
|
||||
}
|
||||
|
||||
if c, ok := s.Client.(ClientLocker); ok {
|
||||
return c.Unlock(id)
|
||||
return c.Unlock(ctx, id)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
package remote
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log"
|
||||
"sync"
|
||||
"testing"
|
||||
@@ -46,10 +47,10 @@ func TestStateRace(t *testing.T) {
|
||||
if err := s.WriteState(current); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if err := s.PersistState(nil); err != nil {
|
||||
if err := s.PersistState(t.Context(), nil); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if err := s.RefreshState(); err != nil {
|
||||
if err := s.RefreshState(t.Context()); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}()
|
||||
@@ -342,7 +343,7 @@ func TestStatePersist(t *testing.T) {
|
||||
// before any writes would happen, so we'll mimic that here for realism.
|
||||
// NB This causes a GET to be logged so the first item in the test cases
|
||||
// must account for this
|
||||
if err := mgr.RefreshState(); err != nil {
|
||||
if err := mgr.RefreshState(t.Context()); err != nil {
|
||||
t.Fatalf("failed to RefreshState: %s", err)
|
||||
}
|
||||
|
||||
@@ -363,7 +364,7 @@ func TestStatePersist(t *testing.T) {
|
||||
if err := mgr.WriteState(s); err != nil {
|
||||
t.Fatalf("failed to WriteState for %q: %s", tc.name, err)
|
||||
}
|
||||
if err := mgr.PersistState(nil); err != nil {
|
||||
if err := mgr.PersistState(t.Context(), nil); err != nil {
|
||||
t.Fatalf("failed to PersistState for %q: %s", tc.name, err)
|
||||
}
|
||||
|
||||
@@ -412,7 +413,7 @@ func TestState_GetRootOutputValues(t *testing.T) {
|
||||
encryption.StateEncryptionDisabled(),
|
||||
)
|
||||
|
||||
outputs, err := mgr.GetRootOutputValues()
|
||||
outputs, err := mgr.GetRootOutputValues(t.Context())
|
||||
if err != nil {
|
||||
t.Errorf("Expected GetRootOutputValues to not return an error, but it returned %v", err)
|
||||
}
|
||||
@@ -528,7 +529,7 @@ func TestWriteStateForMigration(t *testing.T) {
|
||||
// before any writes would happen, so we'll mimic that here for realism.
|
||||
// NB This causes a GET to be logged so the first item in the test cases
|
||||
// must account for this
|
||||
if err := mgr.RefreshState(); err != nil {
|
||||
if err := mgr.RefreshState(t.Context()); err != nil {
|
||||
t.Fatalf("failed to RefreshState: %s", err)
|
||||
}
|
||||
|
||||
@@ -570,7 +571,7 @@ func TestWriteStateForMigration(t *testing.T) {
|
||||
if err := mgr.WriteState(mgr.State()); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := mgr.PersistState(nil); err != nil {
|
||||
if err := mgr.PersistState(t.Context(), nil); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
@@ -689,7 +690,7 @@ func TestWriteStateForMigrationWithForcePushClient(t *testing.T) {
|
||||
// before any writes would happen, so we'll mimic that here for realism.
|
||||
// NB This causes a GET to be logged so the first item in the test cases
|
||||
// must account for this
|
||||
if err := mgr.RefreshState(); err != nil {
|
||||
if err := mgr.RefreshState(t.Context()); err != nil {
|
||||
t.Fatalf("failed to RefreshState: %s", err)
|
||||
}
|
||||
|
||||
@@ -741,7 +742,7 @@ func TestWriteStateForMigrationWithForcePushClient(t *testing.T) {
|
||||
if err := mgr.WriteState(mgr.State()); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := mgr.PersistState(nil); err != nil {
|
||||
if err := mgr.PersistState(t.Context(), nil); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
@@ -773,12 +774,12 @@ type mockClientLocker struct {
|
||||
}
|
||||
|
||||
// Implement the mock Lock method for mockOptionalClientLocker
|
||||
func (c *mockOptionalClientLocker) Lock(_ *statemgr.LockInfo) (string, error) {
|
||||
func (c *mockOptionalClientLocker) Lock(_ context.Context, _ *statemgr.LockInfo) (string, error) {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
// Implement the mock Unlock method for mockOptionalClientLocker
|
||||
func (c *mockOptionalClientLocker) Unlock(_ string) error {
|
||||
func (c *mockOptionalClientLocker) Unlock(_ context.Context, _ string) error {
|
||||
// Provide a simple implementation
|
||||
return nil
|
||||
}
|
||||
@@ -789,12 +790,12 @@ func (c *mockOptionalClientLocker) IsLockingEnabled() bool {
|
||||
}
|
||||
|
||||
// Implement the mock Lock method for mockClientLocker
|
||||
func (c *mockClientLocker) Lock(_ *statemgr.LockInfo) (string, error) {
|
||||
func (c *mockClientLocker) Lock(_ context.Context, _ *statemgr.LockInfo) (string, error) {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
// Implement the mock Unlock method for mockClientLocker
|
||||
func (c *mockClientLocker) Unlock(_ string) error {
|
||||
func (c *mockClientLocker) Unlock(_ context.Context, _ string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -73,14 +73,14 @@ func TestRemoteLocks(t *testing.T, a, b Client) {
|
||||
infoB.Operation = "test"
|
||||
infoB.Who = "clientB"
|
||||
|
||||
lockIDA, err := lockerA.Lock(infoA)
|
||||
lockIDA, err := lockerA.Lock(t.Context(), infoA)
|
||||
if err != nil {
|
||||
t.Fatal("unable to get initial lock:", err)
|
||||
}
|
||||
|
||||
_, err = lockerB.Lock(infoB)
|
||||
_, err = lockerB.Lock(t.Context(), infoB)
|
||||
if err == nil {
|
||||
if err := lockerA.Unlock(lockIDA); err != nil {
|
||||
if err := lockerA.Unlock(t.Context(), lockIDA); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
t.Fatal("client B obtained lock while held by client A")
|
||||
@@ -89,11 +89,11 @@ func TestRemoteLocks(t *testing.T, a, b Client) {
|
||||
t.Errorf("expected a LockError, but was %t: %s", err, err)
|
||||
}
|
||||
|
||||
if err := lockerA.Unlock(lockIDA); err != nil {
|
||||
if err := lockerA.Unlock(t.Context(), lockIDA); err != nil {
|
||||
t.Fatal("error unlocking client A", err)
|
||||
}
|
||||
|
||||
lockIDB, err := lockerB.Lock(infoB)
|
||||
lockIDB, err := lockerB.Lock(t.Context(), infoB)
|
||||
if err != nil {
|
||||
t.Fatal("unable to obtain lock from client B")
|
||||
}
|
||||
@@ -102,7 +102,7 @@ func TestRemoteLocks(t *testing.T, a, b Client) {
|
||||
t.Fatalf("duplicate lock IDs: %q", lockIDB)
|
||||
}
|
||||
|
||||
if err = lockerB.Unlock(lockIDB); err != nil {
|
||||
if err = lockerB.Unlock(t.Context(), lockIDB); err != nil {
|
||||
t.Fatal("error unlocking client B:", err)
|
||||
}
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ package statemgr
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
@@ -158,7 +159,7 @@ func (s *Filesystem) writeState(state *states.State, meta *SnapshotMeta) error {
|
||||
}
|
||||
|
||||
// PersistState writes state to a tfstate file.
|
||||
func (s *Filesystem) PersistState(schemas *tofu.Schemas) error {
|
||||
func (s *Filesystem) PersistState(_ context.Context, schemas *tofu.Schemas) error {
|
||||
defer s.mutex()()
|
||||
|
||||
return s.persistState(schemas)
|
||||
@@ -249,13 +250,13 @@ func (s *Filesystem) persistState(schemas *tofu.Schemas) error {
|
||||
}
|
||||
|
||||
// RefreshState is an implementation of Refresher.
|
||||
func (s *Filesystem) RefreshState() error {
|
||||
func (s *Filesystem) RefreshState(_ context.Context) error {
|
||||
defer s.mutex()()
|
||||
return s.refreshState()
|
||||
}
|
||||
|
||||
func (s *Filesystem) GetRootOutputValues() (map[string]*states.OutputValue, error) {
|
||||
err := s.RefreshState()
|
||||
func (s *Filesystem) GetRootOutputValues(ctx context.Context) (map[string]*states.OutputValue, error) {
|
||||
err := s.RefreshState(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -331,7 +332,7 @@ func (s *Filesystem) refreshState() error {
|
||||
}
|
||||
|
||||
// Lock implements Locker using filesystem discretionary locks.
|
||||
func (s *Filesystem) Lock(info *LockInfo) (string, error) {
|
||||
func (s *Filesystem) Lock(_ context.Context, info *LockInfo) (string, error) {
|
||||
defer s.mutex()()
|
||||
|
||||
if s.stateFileOut == nil {
|
||||
@@ -364,7 +365,7 @@ func (s *Filesystem) Lock(info *LockInfo) (string, error) {
|
||||
}
|
||||
|
||||
// Unlock is the companion to Lock, completing the implementation of Locker.
|
||||
func (s *Filesystem) Unlock(id string) error {
|
||||
func (s *Filesystem) Unlock(_ context.Context, id string) error {
|
||||
defer s.mutex()()
|
||||
|
||||
if s.lockID == "" {
|
||||
|
||||
@@ -59,7 +59,7 @@ func TestFilesystemLocks(t *testing.T) {
|
||||
// lock first
|
||||
info := NewLockInfo()
|
||||
info.Operation = "test"
|
||||
lockID, err := s.Lock(info)
|
||||
lockID, err := s.Lock(t.Context(), info)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -84,22 +84,22 @@ func TestFilesystemLocks(t *testing.T) {
|
||||
}
|
||||
|
||||
// a noop, since we unlock on exit
|
||||
if err := s.Unlock(lockID); err != nil {
|
||||
if err := s.Unlock(t.Context(), lockID); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// local locks can re-lock
|
||||
lockID, err = s.Lock(info)
|
||||
lockID, err = s.Lock(t.Context(), info)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if err := s.Unlock(lockID); err != nil {
|
||||
if err := s.Unlock(t.Context(), lockID); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// we should not be able to unlock the same lock twice
|
||||
if err := s.Unlock(lockID); err == nil {
|
||||
if err := s.Unlock(t.Context(), lockID); err == nil {
|
||||
t.Fatal("unlocking an unlocked state should fail")
|
||||
}
|
||||
|
||||
@@ -120,12 +120,12 @@ func TestFilesystem_writeWhileLocked(t *testing.T) {
|
||||
// lock first
|
||||
info := NewLockInfo()
|
||||
info.Operation = "test"
|
||||
lockID, err := s.Lock(info)
|
||||
lockID, err := s.Lock(t.Context(), info)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer func() {
|
||||
if err := s.Unlock(lockID); err != nil {
|
||||
if err := s.Unlock(t.Context(), lockID); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}()
|
||||
@@ -256,17 +256,17 @@ func TestFilesystem_backupAndReadPath(t *testing.T) {
|
||||
"",
|
||||
)
|
||||
})
|
||||
err = WriteAndPersist(ls, newState, nil)
|
||||
err = WriteAndPersist(t.Context(), ls, newState, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to write new state: %s", err)
|
||||
}
|
||||
|
||||
lockID, err := ls.Lock(info)
|
||||
lockID, err := ls.Lock(t.Context(), info)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if err := ls.Unlock(lockID); err != nil {
|
||||
if err := ls.Unlock(t.Context(), lockID); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
@@ -308,7 +308,7 @@ func TestFilesystem_backupAndReadPath(t *testing.T) {
|
||||
func TestFilesystem_nonExist(t *testing.T) {
|
||||
defer testOverrideVersion(t, "1.2.3")()
|
||||
ls := NewFilesystem("ishouldntexist", encryption.StateEncryptionDisabled())
|
||||
if err := ls.RefreshState(); err != nil {
|
||||
if err := ls.RefreshState(t.Context()); err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
|
||||
@@ -327,7 +327,7 @@ func TestFilesystem_lockUnlockWithoutWrite(t *testing.T) {
|
||||
os.Remove(ls.path)
|
||||
|
||||
// Lock the state, and in doing so recreate the tempfile
|
||||
lockID, err := ls.Lock(info)
|
||||
lockID, err := ls.Lock(t.Context(), info)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -336,7 +336,7 @@ func TestFilesystem_lockUnlockWithoutWrite(t *testing.T) {
|
||||
t.Fatal("should have marked state as created")
|
||||
}
|
||||
|
||||
if err := ls.Unlock(lockID); err != nil {
|
||||
if err := ls.Unlock(t.Context(), lockID); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
@@ -381,7 +381,7 @@ func testFilesystem(t *testing.T) *Filesystem {
|
||||
f.Close()
|
||||
|
||||
ls := NewFilesystem(f.Name(), encryption.StateEncryptionDisabled())
|
||||
if err := ls.RefreshState(); err != nil {
|
||||
if err := ls.RefreshState(t.Context()); err != nil {
|
||||
t.Fatalf("initial refresh failed: %s", err)
|
||||
}
|
||||
|
||||
@@ -413,17 +413,17 @@ func TestFilesystem_refreshWhileLocked(t *testing.T) {
|
||||
// lock first
|
||||
info := NewLockInfo()
|
||||
info.Operation = "test"
|
||||
lockID, err := s.Lock(info)
|
||||
lockID, err := s.Lock(t.Context(), info)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer func() {
|
||||
if err := s.Unlock(lockID); err != nil {
|
||||
if err := s.Unlock(t.Context(), lockID); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}()
|
||||
|
||||
if err := s.RefreshState(); err != nil {
|
||||
if err := s.RefreshState(t.Context()); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
@@ -436,7 +436,7 @@ func TestFilesystem_refreshWhileLocked(t *testing.T) {
|
||||
func TestFilesystem_GetRootOutputValues(t *testing.T) {
|
||||
fs := testFilesystem(t)
|
||||
|
||||
outputs, err := fs.GetRootOutputValues()
|
||||
outputs, err := fs.GetRootOutputValues(t.Context())
|
||||
if err != nil {
|
||||
t.Errorf("Expected GetRootOutputValues to not return an error, but it returned %v", err)
|
||||
}
|
||||
|
||||
@@ -9,6 +9,8 @@ package statemgr
|
||||
// operations done against full state managers.
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/opentofu/opentofu/internal/states"
|
||||
"github.com/opentofu/opentofu/internal/states/statefile"
|
||||
"github.com/opentofu/opentofu/internal/tofu"
|
||||
@@ -30,8 +32,8 @@ func NewStateFile() *statefile.File {
|
||||
//
|
||||
// This is a wrapper around calling RefreshState and then State on the given
|
||||
// manager.
|
||||
func RefreshAndRead(mgr Storage) (*states.State, error) {
|
||||
err := mgr.RefreshState()
|
||||
func RefreshAndRead(ctx context.Context, mgr Storage) (*states.State, error) {
|
||||
err := mgr.RefreshState(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -50,10 +52,10 @@ func RefreshAndRead(mgr Storage) (*states.State, error) {
|
||||
// out quickly with a user-facing error. In situations where more control
|
||||
// is required, call WriteState and PersistState on the state manager directly
|
||||
// and handle their errors.
|
||||
func WriteAndPersist(mgr Storage, state *states.State, schemas *tofu.Schemas) error {
|
||||
func WriteAndPersist(ctx context.Context, mgr Storage, state *states.State, schemas *tofu.Schemas) error {
|
||||
err := mgr.WriteState(state)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return mgr.PersistState(schemas)
|
||||
return mgr.PersistState(ctx, schemas)
|
||||
}
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
package statemgr
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/opentofu/opentofu/internal/states"
|
||||
"github.com/opentofu/opentofu/internal/tofu"
|
||||
)
|
||||
@@ -25,26 +27,26 @@ func (s *LockDisabled) State() *states.State {
|
||||
return s.Inner.State()
|
||||
}
|
||||
|
||||
func (s *LockDisabled) GetRootOutputValues() (map[string]*states.OutputValue, error) {
|
||||
return s.Inner.GetRootOutputValues()
|
||||
func (s *LockDisabled) GetRootOutputValues(ctx context.Context) (map[string]*states.OutputValue, error) {
|
||||
return s.Inner.GetRootOutputValues(ctx)
|
||||
}
|
||||
|
||||
func (s *LockDisabled) WriteState(v *states.State) error {
|
||||
return s.Inner.WriteState(v)
|
||||
}
|
||||
|
||||
func (s *LockDisabled) RefreshState() error {
|
||||
return s.Inner.RefreshState()
|
||||
func (s *LockDisabled) RefreshState(ctx context.Context) error {
|
||||
return s.Inner.RefreshState(ctx)
|
||||
}
|
||||
|
||||
func (s *LockDisabled) PersistState(schemas *tofu.Schemas) error {
|
||||
return s.Inner.PersistState(schemas)
|
||||
func (s *LockDisabled) PersistState(ctx context.Context, schemas *tofu.Schemas) error {
|
||||
return s.Inner.PersistState(ctx, schemas)
|
||||
}
|
||||
|
||||
func (s *LockDisabled) Lock(info *LockInfo) (string, error) {
|
||||
func (s *LockDisabled) Lock(_ context.Context, info *LockInfo) (string, error) {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
func (s *LockDisabled) Unlock(id string) error {
|
||||
func (s *LockDisabled) Unlock(_ context.Context, id string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -55,15 +55,20 @@ type Locker interface {
|
||||
// an instance of LockError immediately if the lock is already held,
|
||||
// and the helper function LockWithContext uses this to automatically
|
||||
// retry lock acquisition periodically until a timeout is reached.
|
||||
Lock(info *LockInfo) (string, error)
|
||||
Lock(ctx context.Context, info *LockInfo) (string, error)
|
||||
|
||||
// Unlock releases a lock previously acquired by Lock.
|
||||
//
|
||||
// Unlocking can potentially be called with the given context already
|
||||
// cancelled. It's the implementer's responsibility to use
|
||||
// [context.WithoutCancel] to create a child context that is not sensitive
|
||||
// to that cancellation when making outgoing requests related to unlocking.
|
||||
//
|
||||
// If the lock cannot be released -- for example, if it was stolen by
|
||||
// another user with some sort of administrative override privilege --
|
||||
// then an error is returned explaining the situation in a way that
|
||||
// is suitable for returning to an end-user.
|
||||
Unlock(id string) error
|
||||
Unlock(ctx context.Context, id string) error
|
||||
}
|
||||
|
||||
// OptionalLocker extends Locker interface to allow callers
|
||||
@@ -88,7 +93,7 @@ func LockWithContext(ctx context.Context, s Locker, info *LockInfo) (string, err
|
||||
delay := time.Second
|
||||
maxDelay := 16 * time.Second
|
||||
for {
|
||||
id, err := s.Lock(info)
|
||||
id, err := s.Lock(ctx, info)
|
||||
if err == nil {
|
||||
return id, nil
|
||||
}
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
package statemgr
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
version "github.com/hashicorp/go-version"
|
||||
|
||||
"github.com/opentofu/opentofu/internal/states"
|
||||
@@ -33,7 +35,7 @@ type Persistent interface {
|
||||
// to differentiate reading the state and reading the outputs within the state.
|
||||
type OutputReader interface {
|
||||
// GetRootOutputValues fetches the root module output values from state or another source
|
||||
GetRootOutputValues() (map[string]*states.OutputValue, error)
|
||||
GetRootOutputValues(context.Context) (map[string]*states.OutputValue, error)
|
||||
}
|
||||
|
||||
// Refresher is the interface for managers that can read snapshots from
|
||||
@@ -63,7 +65,7 @@ type Refresher interface {
|
||||
// return only a subset of what was written. Callers must assume that
|
||||
// ephemeral portions of the state may be unpopulated after calling
|
||||
// RefreshState.
|
||||
RefreshState() error
|
||||
RefreshState(context.Context) error
|
||||
}
|
||||
|
||||
// Persister is the interface for managers that can write snapshots to
|
||||
@@ -73,6 +75,13 @@ type Refresher interface {
|
||||
// PersistState copying the latest transient snapshot to be the new latest
|
||||
// persistent snapshot.
|
||||
//
|
||||
// Persisting can potentially be called with the given context already
|
||||
// cancelled. It's the implementer's responsibility to use
|
||||
// [context.WithoutCancel] to create a child context that is not sensitive
|
||||
// to that cancellation when making outgoing requests related to persisting.
|
||||
// Some callers remove cancellation from the context they pass for their own
|
||||
// reasons, but implementers are not allowed to rely on that.
|
||||
//
|
||||
// A Persister implementation must detect updates made by other processes
|
||||
// that may be running concurrently and avoid destroying those changes. This
|
||||
// is most commonly achieved by making use of atomic write capabilities on
|
||||
@@ -83,7 +92,7 @@ type Refresher interface {
|
||||
// state. For example, when representing state in an external JSON
|
||||
// representation.
|
||||
type Persister interface {
|
||||
PersistState(*tofu.Schemas) error
|
||||
PersistState(context.Context, *tofu.Schemas) error
|
||||
}
|
||||
|
||||
// PersistentMeta is an optional extension to Persistent that allows inspecting
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
package statemgr
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"sync"
|
||||
|
||||
@@ -63,19 +64,19 @@ func (m *fakeFull) WriteState(s *states.State) error {
|
||||
return m.t.WriteState(s)
|
||||
}
|
||||
|
||||
func (m *fakeFull) RefreshState() error {
|
||||
func (m *fakeFull) RefreshState(_ context.Context) error {
|
||||
return m.t.WriteState(m.fakeP.State())
|
||||
}
|
||||
|
||||
func (m *fakeFull) PersistState(schemas *tofu.Schemas) error {
|
||||
func (m *fakeFull) PersistState(_ context.Context, schemas *tofu.Schemas) error {
|
||||
return m.fakeP.WriteState(m.t.State())
|
||||
}
|
||||
|
||||
func (m *fakeFull) GetRootOutputValues() (map[string]*states.OutputValue, error) {
|
||||
func (m *fakeFull) GetRootOutputValues(_ context.Context) (map[string]*states.OutputValue, error) {
|
||||
return m.State().RootModule().OutputValues, nil
|
||||
}
|
||||
|
||||
func (m *fakeFull) Lock(info *LockInfo) (string, error) {
|
||||
func (m *fakeFull) Lock(_ context.Context, info *LockInfo) (string, error) {
|
||||
m.lockLock.Lock()
|
||||
defer m.lockLock.Unlock()
|
||||
|
||||
@@ -90,7 +91,7 @@ func (m *fakeFull) Lock(info *LockInfo) (string, error) {
|
||||
return "placeholder", nil
|
||||
}
|
||||
|
||||
func (m *fakeFull) Unlock(id string) error {
|
||||
func (m *fakeFull) Unlock(_ context.Context, id string) error {
|
||||
m.lockLock.Lock()
|
||||
defer m.lockLock.Unlock()
|
||||
|
||||
@@ -121,7 +122,7 @@ func (m *fakeErrorFull) State() *states.State {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *fakeErrorFull) GetRootOutputValues() (map[string]*states.OutputValue, error) {
|
||||
func (m *fakeErrorFull) GetRootOutputValues(_ context.Context) (map[string]*states.OutputValue, error) {
|
||||
return nil, errors.New("fake state manager error")
|
||||
}
|
||||
|
||||
@@ -129,18 +130,18 @@ func (m *fakeErrorFull) WriteState(s *states.State) error {
|
||||
return errors.New("fake state manager error")
|
||||
}
|
||||
|
||||
func (m *fakeErrorFull) RefreshState() error {
|
||||
func (m *fakeErrorFull) RefreshState(_ context.Context) error {
|
||||
return errors.New("fake state manager error")
|
||||
}
|
||||
|
||||
func (m *fakeErrorFull) PersistState(schemas *tofu.Schemas) error {
|
||||
func (m *fakeErrorFull) PersistState(_ context.Context, schemas *tofu.Schemas) error {
|
||||
return errors.New("fake state manager error")
|
||||
}
|
||||
|
||||
func (m *fakeErrorFull) Lock(info *LockInfo) (string, error) {
|
||||
func (m *fakeErrorFull) Lock(_ context.Context, info *LockInfo) (string, error) {
|
||||
return "placeholder", nil
|
||||
}
|
||||
|
||||
func (m *fakeErrorFull) Unlock(id string) error {
|
||||
func (m *fakeErrorFull) Unlock(_ context.Context, id string) error {
|
||||
return errors.New("fake state manager error")
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ func TestNewLockInfo(t *testing.T) {
|
||||
func TestLockWithContext(t *testing.T) {
|
||||
s := NewFullFake(nil, TestFullInitialState())
|
||||
|
||||
id, err := s.Lock(NewLockInfo())
|
||||
id, err := s.Lock(t.Context(), NewLockInfo())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -76,7 +76,7 @@ func TestLockWithContext(t *testing.T) {
|
||||
go func() {
|
||||
defer close(unlocked)
|
||||
<-attempted
|
||||
unlockErr = s.Unlock(id)
|
||||
unlockErr = s.Unlock(t.Context(), id)
|
||||
}()
|
||||
|
||||
ctx, cancel = context.WithTimeout(context.Background(), 2*time.Second)
|
||||
|
||||
@@ -27,7 +27,7 @@ import (
|
||||
func TestFull(t *testing.T, s Full) {
|
||||
t.Helper()
|
||||
|
||||
if err := s.RefreshState(); err != nil {
|
||||
if err := s.RefreshState(t.Context()); err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
|
||||
@@ -61,12 +61,12 @@ func TestFull(t *testing.T, s Full) {
|
||||
}
|
||||
|
||||
// Test persistence
|
||||
if err := s.PersistState(nil); err != nil {
|
||||
if err := s.PersistState(t.Context(), nil); err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
|
||||
// Refresh if we got it
|
||||
if err := s.RefreshState(); err != nil {
|
||||
if err := s.RefreshState(t.Context()); err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
|
||||
@@ -86,7 +86,7 @@ func TestFull(t *testing.T, s Full) {
|
||||
if err := s.WriteState(current); err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
if err := s.PersistState(nil); err != nil {
|
||||
if err := s.PersistState(t.Context(), nil); err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
|
||||
@@ -109,7 +109,7 @@ func TestFull(t *testing.T, s Full) {
|
||||
if err := s.WriteState(current); err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
if err := s.PersistState(nil); err != nil {
|
||||
if err := s.PersistState(t.Context(), nil); err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user