This commit is contained in:
Martin Atkins
2025-06-24 14:17:34 -07:00
parent 5e18e20b98
commit 44897af258
83 changed files with 411 additions and 368 deletions

View File

@@ -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.

View File

@@ -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.

View File

@@ -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
}

View File

@@ -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")
}

View File

@@ -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)

View File

@@ -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

View File

@@ -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")
}

View File

@@ -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
}

View File

@@ -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
}

View File

@@ -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

View File

@@ -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
}

View File

@@ -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

View File

@@ -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)
}
}

View File

@@ -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
}

View File

@@ -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)
}

View File

@@ -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
}

View File

@@ -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)

View File

@@ -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)
}

View File

@@ -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
}

View File

@@ -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)
}
}

View File

@@ -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)
}

View File

@@ -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)
}

View File

@@ -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)
}

View File

@@ -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

View File

@@ -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")
}
}

View File

@@ -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
}

View File

@@ -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
}

View File

@@ -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")
}
}

View File

@@ -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
}

View File

@@ -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())
}
}

View File

@@ -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
}

View File

@@ -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")
}

View File

@@ -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())
}
}

View File

@@ -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)
}
}

View File

@@ -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)
}

View File

@@ -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
}

View File

@@ -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())
}
}

View File

@@ -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
}

View File

@@ -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")
}

View File

@@ -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())
}

View File

@@ -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())
}
}

View File

@@ -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)
}

View File

@@ -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)
}

View File

@@ -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)
}

View File

@@ -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()

View File

@@ -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 {

View File

@@ -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
}

View File

@@ -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
}

View File

@@ -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)
}

View File

@@ -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
}

View File

@@ -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)
}

View File

@@ -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)
}

View File

@@ -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)
}

View File

@@ -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
}

View File

@@ -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()

View File

@@ -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)
}

View File

@@ -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
}

View File

@@ -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
}

View File

@@ -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
}

View File

@@ -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
}

View File

@@ -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)
}

View File

@@ -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
}

View File

@@ -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
}

View File

@@ -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
}

View File

@@ -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
}

View File

@@ -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
}

View File

@@ -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
}

View File

@@ -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)
}

View File

@@ -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())

View File

@@ -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

View File

@@ -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")
}
}

View File

@@ -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
}

View File

@@ -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
}

View File

@@ -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)
}

View File

@@ -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 == "" {

View File

@@ -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)
}

View File

@@ -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)
}

View File

@@ -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
}

View File

@@ -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
}

View File

@@ -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

View File

@@ -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")
}

View File

@@ -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)

View File

@@ -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)
}