Make backend.StateMgr accept a context (#780)

Signed-off-by: Marcin Wyszynski <marcin.pixie@gmail.com>
This commit is contained in:
Marcin Wyszynski 2023-10-24 15:47:46 +02:00 committed by GitHub
parent f906c4792a
commit a6a54c3777
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
71 changed files with 534 additions and 268 deletions

View File

@ -105,7 +105,7 @@ type Backend interface {
// If the named workspace doesn't exist, or if it has no state, it will // If the named workspace doesn't exist, or if it has no state, it will
// be created either immediately on this call or the first time // be created either immediately on this call or the first time
// PersistState is called, depending on the state manager implementation. // PersistState is called, depending on the state manager implementation.
StateMgr(workspace string) (statemgr.Full, error) StateMgr(_ context.Context, workspace string) (statemgr.Full, error)
// DeleteWorkspace removes the workspace with the given name if it exists. // DeleteWorkspace removes the workspace with the given name if it exists.
// //

View File

@ -238,10 +238,10 @@ func (b *Local) DeleteWorkspace(name string, force bool) error {
return os.RemoveAll(filepath.Join(b.stateWorkspaceDir(), name)) return os.RemoveAll(filepath.Join(b.stateWorkspaceDir(), name))
} }
func (b *Local) StateMgr(name string) (statemgr.Full, error) { func (b *Local) StateMgr(ctx context.Context, name string) (statemgr.Full, error) {
// If we have a backend handling state, delegate to that. // If we have a backend handling state, delegate to that.
if b.Backend != nil { if b.Backend != nil {
return b.Backend.StateMgr(name) return b.Backend.StateMgr(ctx, name)
} }
if s, ok := b.states[name]; ok { if s, ok := b.states[name]; ok {

View File

@ -347,7 +347,7 @@ type backendWithFailingState struct {
Local Local
} }
func (b *backendWithFailingState) StateMgr(name string) (statemgr.Full, error) { func (b *backendWithFailingState) StateMgr(_ context.Context, name string) (statemgr.Full, error) {
return &failingState{ return &failingState{
statemgr.NewFilesystem("failing-state.tfstate"), statemgr.NewFilesystem("failing-state.tfstate"),
}, nil }, nil

View File

@ -39,9 +39,11 @@ func (b *Local) LocalRun(op *backend.Operation) (*backend.LocalRun, statemgr.Ful
func (b *Local) localRun(op *backend.Operation) (*backend.LocalRun, *configload.Snapshot, statemgr.Full, tfdiags.Diagnostics) { func (b *Local) localRun(op *backend.Operation) (*backend.LocalRun, *configload.Snapshot, statemgr.Full, tfdiags.Diagnostics) {
var diags tfdiags.Diagnostics var diags tfdiags.Diagnostics
ctx := context.TODO()
// Get the latest state. // Get the latest state.
log.Printf("[TRACE] backend/local: requesting state manager for workspace %q", op.Workspace) log.Printf("[TRACE] backend/local: requesting state manager for workspace %q", op.Workspace)
s, err := b.StateMgr(op.Workspace) s, err := b.StateMgr(ctx, op.Workspace)
if err != nil { if err != nil {
diags = diags.Append(fmt.Errorf("error loading state: %w", err)) diags = diags.Append(fmt.Errorf("error loading state: %w", err))
return nil, nil, nil, diags return nil, nil, nil, diags

View File

@ -138,8 +138,10 @@ func TestLocalRun_stalePlan(t *testing.T) {
t.Fatalf("unexpected error writing state file: %s", err) t.Fatalf("unexpected error writing state file: %s", err)
} }
ctx := context.Background()
// Refresh the state // Refresh the state
sm, err := b.StateMgr("") sm, err := b.StateMgr(ctx, "")
if err != nil { if err != nil {
t.Fatalf("unexpected error: %s", err) t.Fatalf("unexpected error: %s", err)
} }
@ -213,7 +215,7 @@ type backendWithStateStorageThatFailsRefresh struct {
var _ backend.Backend = backendWithStateStorageThatFailsRefresh{} var _ backend.Backend = backendWithStateStorageThatFailsRefresh{}
func (b backendWithStateStorageThatFailsRefresh) StateMgr(workspace string) (statemgr.Full, error) { func (b backendWithStateStorageThatFailsRefresh) StateMgr(_ context.Context, workspace string) (statemgr.Full, error) {
return &stateStorageThatFailsRefresh{}, nil return &stateStorageThatFailsRefresh{}, nil
} }

View File

@ -4,6 +4,7 @@
package local package local
import ( import (
"context"
"errors" "errors"
"os" "os"
"path/filepath" "path/filepath"
@ -106,8 +107,10 @@ func TestLocal_addAndRemoveStates(t *testing.T) {
t.Fatalf("expected []string{%q}, got %q", dflt, states) t.Fatalf("expected []string{%q}, got %q", dflt, states)
} }
ctx := context.Background()
expectedA := "test_A" expectedA := "test_A"
if _, err := b.StateMgr(expectedA); err != nil { if _, err := b.StateMgr(ctx, expectedA); err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -122,7 +125,7 @@ func TestLocal_addAndRemoveStates(t *testing.T) {
} }
expectedB := "test_B" expectedB := "test_B"
if _, err := b.StateMgr(expectedB); err != nil { if _, err := b.StateMgr(ctx, expectedB); err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -184,7 +187,7 @@ var errTestDelegateState = errors.New("state called")
var errTestDelegateStates = errors.New("states called") var errTestDelegateStates = errors.New("states called")
var errTestDelegateDeleteState = errors.New("delete called") var errTestDelegateDeleteState = errors.New("delete called")
func (b *testDelegateBackend) StateMgr(name string) (statemgr.Full, error) { func (b *testDelegateBackend) StateMgr(_ context.Context, name string) (statemgr.Full, error) {
if b.stateErr { if b.stateErr {
return nil, errTestDelegateState return nil, errTestDelegateState
} }
@ -215,7 +218,7 @@ func TestLocal_multiStateBackend(t *testing.T) {
deleteErr: true, deleteErr: true,
}) })
if _, err := b.StateMgr("test"); err != errTestDelegateState { if _, err := b.StateMgr(context.Background(), "test"); err != errTestDelegateState {
t.Fatal("expected errTestDelegateState, got:", err) t.Fatal("expected errTestDelegateState, got:", err)
} }

View File

@ -4,6 +4,7 @@
package local package local
import ( import (
"context"
"path/filepath" "path/filepath"
"testing" "testing"
@ -125,12 +126,12 @@ func (b *TestLocalSingleState) DeleteWorkspace(string, bool) error {
return backend.ErrWorkspacesNotSupported return backend.ErrWorkspacesNotSupported
} }
func (b *TestLocalSingleState) StateMgr(name string) (statemgr.Full, error) { func (b *TestLocalSingleState) StateMgr(ctx context.Context, name string) (statemgr.Full, error) {
if name != backend.DefaultStateName { if name != backend.DefaultStateName {
return nil, backend.ErrWorkspacesNotSupported return nil, backend.ErrWorkspacesNotSupported
} }
return b.Local.StateMgr(name) return b.Local.StateMgr(ctx, name)
} }
// TestLocalNoDefaultState is a backend implementation that wraps // TestLocalNoDefaultState is a backend implementation that wraps
@ -170,11 +171,11 @@ func (b *TestLocalNoDefaultState) DeleteWorkspace(name string, force bool) error
return b.Local.DeleteWorkspace(name, force) return b.Local.DeleteWorkspace(name, force)
} }
func (b *TestLocalNoDefaultState) StateMgr(name string) (statemgr.Full, error) { func (b *TestLocalNoDefaultState) StateMgr(ctx context.Context, name string) (statemgr.Full, error) {
if name == backend.DefaultStateName { if name == backend.DefaultStateName {
return nil, backend.ErrDefaultWorkspaceNotSupported return nil, backend.ErrDefaultWorkspaceNotSupported
} }
return b.Local.StateMgr(name) return b.Local.StateMgr(ctx, name)
} }
func testStateFile(t *testing.T, path string, s *states.State) { func testStateFile(t *testing.T, path string, s *states.State) {
@ -203,7 +204,10 @@ func mustResourceInstanceAddr(s string) addrs.AbsResourceInstance {
// return true. // return true.
func assertBackendStateUnlocked(t *testing.T, b *Local) bool { func assertBackendStateUnlocked(t *testing.T, b *Local) bool {
t.Helper() t.Helper()
stateMgr, _ := b.StateMgr(backend.DefaultStateName)
ctx := context.Background()
stateMgr, _ := b.StateMgr(ctx, backend.DefaultStateName)
if _, err := stateMgr.Lock(statemgr.NewLockInfo()); err != nil { if _, err := stateMgr.Lock(statemgr.NewLockInfo()); err != nil {
t.Errorf("state is already locked: %s", err.Error()) t.Errorf("state is already locked: %s", err.Error())
return false return false
@ -216,7 +220,10 @@ func assertBackendStateUnlocked(t *testing.T, b *Local) bool {
// return false. // return false.
func assertBackendStateLocked(t *testing.T, b *Local) bool { func assertBackendStateLocked(t *testing.T, b *Local) bool {
t.Helper() t.Helper()
stateMgr, _ := b.StateMgr(backend.DefaultStateName)
ctx := context.Background()
stateMgr, _ := b.StateMgr(ctx, backend.DefaultStateName)
if _, err := stateMgr.Lock(statemgr.NewLockInfo()); err != nil { if _, err := stateMgr.Lock(statemgr.NewLockInfo()); err != nil {
return true return true
} }

View File

@ -81,8 +81,7 @@ func (b *Backend) DeleteWorkspace(name string, _ bool) error {
return nil return nil
} }
func (b *Backend) StateMgr(name string) (statemgr.Full, error) { func (b *Backend) StateMgr(ctx context.Context, name string) (statemgr.Full, error) {
ctx := context.TODO()
blobClient, err := b.armClient.getBlobClient(ctx) blobClient, err := b.armClient.getBlobClient(ctx)
if err != nil { if err != nil {
return nil, err return nil, err
@ -149,10 +148,6 @@ func (b *Backend) StateMgr(name string) (statemgr.Full, error) {
return stateMgr, nil return stateMgr, nil
} }
func (b *Backend) client() *RemoteClient {
return &RemoteClient{}
}
func (b *Backend) path(name string) string { func (b *Backend) path(name string) string {
if name == backend.DefaultStateName { if name == backend.DefaultStateName {
return b.keyName return b.keyName

View File

@ -25,7 +25,7 @@ func TestRemoteClientAccessKeyBasic(t *testing.T) {
res := testResourceNames(rs, "testState") res := testResourceNames(rs, "testState")
armClient := buildTestClient(t, res) armClient := buildTestClient(t, res)
ctx := context.TODO() ctx := context.Background()
err := armClient.buildTestResources(ctx, &res) err := armClient.buildTestResources(ctx, &res)
defer armClient.destroyTestResources(ctx, res) defer armClient.destroyTestResources(ctx, res)
if err != nil { if err != nil {
@ -41,7 +41,7 @@ func TestRemoteClientAccessKeyBasic(t *testing.T) {
"endpoint": os.Getenv("ARM_ENDPOINT"), "endpoint": os.Getenv("ARM_ENDPOINT"),
})).(*Backend) })).(*Backend)
state, err := b.StateMgr(backend.DefaultStateName) state, err := b.StateMgr(ctx, backend.DefaultStateName)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -55,7 +55,7 @@ func TestRemoteClientManagedServiceIdentityBasic(t *testing.T) {
res := testResourceNames(rs, "testState") res := testResourceNames(rs, "testState")
armClient := buildTestClient(t, res) armClient := buildTestClient(t, res)
ctx := context.TODO() ctx := context.Background()
err := armClient.buildTestResources(ctx, &res) err := armClient.buildTestResources(ctx, &res)
defer armClient.destroyTestResources(ctx, res) defer armClient.destroyTestResources(ctx, res)
if err != nil { if err != nil {
@ -74,7 +74,7 @@ func TestRemoteClientManagedServiceIdentityBasic(t *testing.T) {
"endpoint": os.Getenv("ARM_ENDPOINT"), "endpoint": os.Getenv("ARM_ENDPOINT"),
})).(*Backend) })).(*Backend)
state, err := b.StateMgr(backend.DefaultStateName) state, err := b.StateMgr(ctx, backend.DefaultStateName)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -88,7 +88,7 @@ func TestRemoteClientSasTokenBasic(t *testing.T) {
res := testResourceNames(rs, "testState") res := testResourceNames(rs, "testState")
armClient := buildTestClient(t, res) armClient := buildTestClient(t, res)
ctx := context.TODO() ctx := context.Background()
err := armClient.buildTestResources(ctx, &res) err := armClient.buildTestResources(ctx, &res)
defer armClient.destroyTestResources(ctx, res) defer armClient.destroyTestResources(ctx, res)
if err != nil { if err != nil {
@ -109,7 +109,7 @@ func TestRemoteClientSasTokenBasic(t *testing.T) {
"endpoint": os.Getenv("ARM_ENDPOINT"), "endpoint": os.Getenv("ARM_ENDPOINT"),
})).(*Backend) })).(*Backend)
state, err := b.StateMgr(backend.DefaultStateName) state, err := b.StateMgr(ctx, backend.DefaultStateName)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -123,7 +123,7 @@ func TestRemoteClientServicePrincipalBasic(t *testing.T) {
res := testResourceNames(rs, "testState") res := testResourceNames(rs, "testState")
armClient := buildTestClient(t, res) armClient := buildTestClient(t, res)
ctx := context.TODO() ctx := context.Background()
err := armClient.buildTestResources(ctx, &res) err := armClient.buildTestResources(ctx, &res)
defer armClient.destroyTestResources(ctx, res) defer armClient.destroyTestResources(ctx, res)
if err != nil { if err != nil {
@ -143,7 +143,7 @@ func TestRemoteClientServicePrincipalBasic(t *testing.T) {
"endpoint": os.Getenv("ARM_ENDPOINT"), "endpoint": os.Getenv("ARM_ENDPOINT"),
})).(*Backend) })).(*Backend)
state, err := b.StateMgr(backend.DefaultStateName) state, err := b.StateMgr(ctx, backend.DefaultStateName)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -157,7 +157,7 @@ func TestRemoteClientAccessKeyLocks(t *testing.T) {
res := testResourceNames(rs, "testState") res := testResourceNames(rs, "testState")
armClient := buildTestClient(t, res) armClient := buildTestClient(t, res)
ctx := context.TODO() ctx := context.Background()
err := armClient.buildTestResources(ctx, &res) err := armClient.buildTestResources(ctx, &res)
defer armClient.destroyTestResources(ctx, res) defer armClient.destroyTestResources(ctx, res)
if err != nil { if err != nil {
@ -182,12 +182,12 @@ func TestRemoteClientAccessKeyLocks(t *testing.T) {
"endpoint": os.Getenv("ARM_ENDPOINT"), "endpoint": os.Getenv("ARM_ENDPOINT"),
})).(*Backend) })).(*Backend)
s1, err := b1.StateMgr(backend.DefaultStateName) s1, err := b1.StateMgr(ctx, backend.DefaultStateName)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
s2, err := b2.StateMgr(backend.DefaultStateName) s2, err := b2.StateMgr(ctx, backend.DefaultStateName)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -201,7 +201,7 @@ func TestRemoteClientServicePrincipalLocks(t *testing.T) {
res := testResourceNames(rs, "testState") res := testResourceNames(rs, "testState")
armClient := buildTestClient(t, res) armClient := buildTestClient(t, res)
ctx := context.TODO() ctx := context.Background()
err := armClient.buildTestResources(ctx, &res) err := armClient.buildTestResources(ctx, &res)
defer armClient.destroyTestResources(ctx, res) defer armClient.destroyTestResources(ctx, res)
if err != nil { if err != nil {
@ -234,12 +234,12 @@ func TestRemoteClientServicePrincipalLocks(t *testing.T) {
"endpoint": os.Getenv("ARM_ENDPOINT"), "endpoint": os.Getenv("ARM_ENDPOINT"),
})).(*Backend) })).(*Backend)
s1, err := b1.StateMgr(backend.DefaultStateName) s1, err := b1.StateMgr(ctx, backend.DefaultStateName)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
s2, err := b2.StateMgr(backend.DefaultStateName) s2, err := b2.StateMgr(ctx, backend.DefaultStateName)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }

View File

@ -4,6 +4,7 @@
package consul package consul
import ( import (
"context"
"fmt" "fmt"
"strings" "strings"
@ -45,7 +46,7 @@ func (b *Backend) Workspaces() ([]string, error) {
result := make([]string, 1, len(envs)+1) result := make([]string, 1, len(envs)+1)
result[0] = backend.DefaultStateName result[0] = backend.DefaultStateName
for k, _ := range envs { for k := range envs {
result = append(result, k) result = append(result, k)
} }
@ -66,7 +67,7 @@ func (b *Backend) DeleteWorkspace(name string, _ bool) error {
return err return err
} }
func (b *Backend) StateMgr(name string) (statemgr.Full, error) { func (b *Backend) StateMgr(ctx context.Context, name string) (statemgr.Full, error) {
// Determine the path of the data // Determine the path of the data
path := b.path(name) path := b.path(name)

View File

@ -42,8 +42,10 @@ func TestRemoteClient(t *testing.T) {
"path": path, "path": path,
})) }))
ctx := context.Background()
// Grab the client // Grab the client
state, err := b.StateMgr(backend.DefaultStateName) state, err := b.StateMgr(ctx, backend.DefaultStateName)
if err != nil { if err != nil {
t.Fatalf("err: %s", err) t.Fatalf("err: %s", err)
} }
@ -66,8 +68,10 @@ func TestRemoteClient_gzipUpgrade(t *testing.T) {
"path": statePath, "path": statePath,
})) }))
ctx := context.Background()
// Grab the client // Grab the client
state, err := b.StateMgr(backend.DefaultStateName) state, err := b.StateMgr(ctx, backend.DefaultStateName)
if err != nil { if err != nil {
t.Fatalf("err: %s", err) t.Fatalf("err: %s", err)
} }
@ -83,7 +87,7 @@ func TestRemoteClient_gzipUpgrade(t *testing.T) {
})) }))
// Grab the client // Grab the client
state, err = b.StateMgr(backend.DefaultStateName) state, err = b.StateMgr(ctx, backend.DefaultStateName)
if err != nil { if err != nil {
t.Fatalf("err: %s", err) t.Fatalf("err: %s", err)
} }
@ -105,7 +109,9 @@ func TestConsul_largeState(t *testing.T) {
"path": path, "path": path,
})) }))
s, err := b.StateMgr(backend.DefaultStateName) ctx := context.Background()
s, err := b.StateMgr(ctx, backend.DefaultStateName)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -192,7 +198,7 @@ func TestConsul_largeState(t *testing.T) {
"gzip": true, "gzip": true,
})) }))
s, err = b.StateMgr(backend.DefaultStateName) s, err = b.StateMgr(ctx, backend.DefaultStateName)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -245,12 +251,14 @@ func TestConsul_stateLock(t *testing.T) {
} }
for _, path := range testCases { for _, path := range testCases {
ctx := context.Background()
t.Run(path, func(*testing.T) { t.Run(path, func(*testing.T) {
// create 2 instances to get 2 remote.Clients // create 2 instances to get 2 remote.Clients
sA, err := backend.TestBackendConfig(t, New(), backend.TestWrapConfig(map[string]interface{}{ sA, err := backend.TestBackendConfig(t, New(), backend.TestWrapConfig(map[string]interface{}{
"address": srv.HTTPAddr, "address": srv.HTTPAddr,
"path": path, "path": path,
})).StateMgr(backend.DefaultStateName) })).StateMgr(ctx, backend.DefaultStateName)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -258,7 +266,7 @@ func TestConsul_stateLock(t *testing.T) {
sB, err := backend.TestBackendConfig(t, New(), backend.TestWrapConfig(map[string]interface{}{ sB, err := backend.TestBackendConfig(t, New(), backend.TestWrapConfig(map[string]interface{}{
"address": srv.HTTPAddr, "address": srv.HTTPAddr,
"path": path, "path": path,
})).StateMgr(backend.DefaultStateName) })).StateMgr(ctx, backend.DefaultStateName)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -289,6 +297,8 @@ func TestConsul_destroyLock(t *testing.T) {
for _, path := range testCases { for _, path := range testCases {
t.Run(path, func(*testing.T) { t.Run(path, func(*testing.T) {
ctx := context.Background()
// Get the backend // Get the backend
b := backend.TestBackendConfig(t, New(), backend.TestWrapConfig(map[string]interface{}{ b := backend.TestBackendConfig(t, New(), backend.TestWrapConfig(map[string]interface{}{
"address": srv.HTTPAddr, "address": srv.HTTPAddr,
@ -296,7 +306,7 @@ func TestConsul_destroyLock(t *testing.T) {
})) }))
// Grab the client // Grab the client
s, err := b.StateMgr(backend.DefaultStateName) s, err := b.StateMgr(ctx, backend.DefaultStateName)
if err != nil { if err != nil {
t.Fatalf("err: %s", err) t.Fatalf("err: %s", err)
} }
@ -319,7 +329,7 @@ func TestConsul_destroyLock(t *testing.T) {
// The release the lock from a second client to test the // The release the lock from a second client to test the
// `tofu force-unlock <lock_id>` functionality // `tofu force-unlock <lock_id>` functionality
s, err = b.StateMgr(backend.DefaultStateName) s, err = b.StateMgr(ctx, backend.DefaultStateName)
if err != nil { if err != nil {
t.Fatalf("err: %s", err) t.Fatalf("err: %s", err)
} }
@ -355,11 +365,13 @@ func TestConsul_lostLock(t *testing.T) {
path := fmt.Sprintf("tf-unit/%s", time.Now().String()) path := fmt.Sprintf("tf-unit/%s", time.Now().String())
ctx := context.Background()
// create 2 instances to get 2 remote.Clients // create 2 instances to get 2 remote.Clients
sA, err := backend.TestBackendConfig(t, New(), backend.TestWrapConfig(map[string]interface{}{ sA, err := backend.TestBackendConfig(t, New(), backend.TestWrapConfig(map[string]interface{}{
"address": srv.HTTPAddr, "address": srv.HTTPAddr,
"path": path, "path": path,
})).StateMgr(backend.DefaultStateName) })).StateMgr(ctx, backend.DefaultStateName)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -367,7 +379,7 @@ func TestConsul_lostLock(t *testing.T) {
sB, err := backend.TestBackendConfig(t, New(), backend.TestWrapConfig(map[string]interface{}{ sB, err := backend.TestBackendConfig(t, New(), backend.TestWrapConfig(map[string]interface{}{
"address": srv.HTTPAddr, "address": srv.HTTPAddr,
"path": path + "-not-used", "path": path + "-not-used",
})).StateMgr(backend.DefaultStateName) })).StateMgr(ctx, backend.DefaultStateName)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -418,7 +430,9 @@ func TestConsul_lostLockConnection(t *testing.T) {
"path": path, "path": path,
})) }))
s, err := b.StateMgr(backend.DefaultStateName) ctx := context.Background()
s, err := b.StateMgr(ctx, backend.DefaultStateName)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }

View File

@ -4,6 +4,7 @@
package cos package cos
import ( import (
"context"
"fmt" "fmt"
"log" "log"
"path" "path"
@ -76,7 +77,7 @@ func (b *Backend) DeleteWorkspace(name string, _ bool) error {
} }
// StateMgr manage the state, if the named state not exists, a new file will created // StateMgr manage the state, if the named state not exists, a new file will created
func (b *Backend) StateMgr(name string) (statemgr.Full, error) { func (b *Backend) StateMgr(ctx context.Context, name string) (statemgr.Full, error) {
log.Printf("[DEBUG] state manager, current workspace: %v", name) log.Printf("[DEBUG] state manager, current workspace: %v", name)
c, err := b.client(name) c, err := b.client(name)

View File

@ -4,6 +4,7 @@
package cos package cos
import ( import (
"context"
"crypto/md5" "crypto/md5"
"fmt" "fmt"
"os" "os"
@ -63,7 +64,9 @@ func TestRemoteClient(t *testing.T) {
be := setupBackend(t, bucket, defaultPrefix, defaultKey, false) be := setupBackend(t, bucket, defaultPrefix, defaultKey, false)
defer teardownBackend(t, be) defer teardownBackend(t, be)
ss, err := be.StateMgr(backend.DefaultStateName) ctx := context.Background()
ss, err := be.StateMgr(ctx, backend.DefaultStateName)
if err != nil { if err != nil {
t.Fatalf("unexpected error: %s", err) t.Fatalf("unexpected error: %s", err)
} }
@ -85,7 +88,9 @@ func TestRemoteClientWithPrefix(t *testing.T) {
be := setupBackend(t, bucket, prefix, defaultKey, false) be := setupBackend(t, bucket, prefix, defaultKey, false)
defer teardownBackend(t, be) defer teardownBackend(t, be)
ss, err := be.StateMgr(backend.DefaultStateName) ctx := context.Background()
ss, err := be.StateMgr(ctx, backend.DefaultStateName)
if err != nil { if err != nil {
t.Fatalf("unexpected error: %s", err) t.Fatalf("unexpected error: %s", err)
} }
@ -106,7 +111,9 @@ func TestRemoteClientWithEncryption(t *testing.T) {
be := setupBackend(t, bucket, defaultPrefix, defaultKey, true) be := setupBackend(t, bucket, defaultPrefix, defaultKey, true)
defer teardownBackend(t, be) defer teardownBackend(t, be)
ss, err := be.StateMgr(backend.DefaultStateName) ctx := context.Background()
ss, err := be.StateMgr(ctx, backend.DefaultStateName)
if err != nil { if err != nil {
t.Fatalf("unexpected error: %s", err) t.Fatalf("unexpected error: %s", err)
} }
@ -128,7 +135,9 @@ func TestRemoteLocks(t *testing.T) {
defer teardownBackend(t, be) defer teardownBackend(t, be)
remoteClient := func() (remote.Client, error) { remoteClient := func() (remote.Client, error) {
ss, err := be.StateMgr(backend.DefaultStateName) ctx := context.Background()
ss, err := be.StateMgr(ctx, backend.DefaultStateName)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -4,6 +4,7 @@
package gcs package gcs
import ( import (
"context"
"fmt" "fmt"
"path" "path"
"sort" "sort"
@ -90,7 +91,7 @@ func (b *Backend) client(name string) (*remoteClient, error) {
// StateMgr reads and returns the named state from GCS. If the named state does // StateMgr reads and returns the named state from GCS. If the named state does
// not yet exist, a new state file is created. // not yet exist, a new state file is created.
func (b *Backend) StateMgr(name string) (statemgr.Full, error) { func (b *Backend) StateMgr(ctx context.Context, name string) (statemgr.Full, error) {
c, err := b.client(name) c, err := b.client(name)
if err != nil { if err != nil {
return nil, err return nil, err

View File

@ -79,7 +79,9 @@ func TestRemoteClient(t *testing.T) {
be := setupBackend(t, bucket, noPrefix, noEncryptionKey, noKmsKeyName) be := setupBackend(t, bucket, noPrefix, noEncryptionKey, noKmsKeyName)
defer teardownBackend(t, be, noPrefix) defer teardownBackend(t, be, noPrefix)
ss, err := be.StateMgr(backend.DefaultStateName) ctx := context.Background()
ss, err := be.StateMgr(ctx, backend.DefaultStateName)
if err != nil { if err != nil {
t.Fatalf("be.StateMgr(%q) = %v", backend.DefaultStateName, err) t.Fatalf("be.StateMgr(%q) = %v", backend.DefaultStateName, err)
} }
@ -98,7 +100,9 @@ func TestRemoteClientWithEncryption(t *testing.T) {
be := setupBackend(t, bucket, noPrefix, encryptionKey, noKmsKeyName) be := setupBackend(t, bucket, noPrefix, encryptionKey, noKmsKeyName)
defer teardownBackend(t, be, noPrefix) defer teardownBackend(t, be, noPrefix)
ss, err := be.StateMgr(backend.DefaultStateName) ctx := context.Background()
ss, err := be.StateMgr(ctx, backend.DefaultStateName)
if err != nil { if err != nil {
t.Fatalf("be.StateMgr(%q) = %v", backend.DefaultStateName, err) t.Fatalf("be.StateMgr(%q) = %v", backend.DefaultStateName, err)
} }
@ -119,7 +123,9 @@ func TestRemoteLocks(t *testing.T) {
defer teardownBackend(t, be, noPrefix) defer teardownBackend(t, be, noPrefix)
remoteClient := func() (remote.Client, error) { remoteClient := func() (remote.Client, error) {
ss, err := be.StateMgr(backend.DefaultStateName) ctx := context.Background()
ss, err := be.StateMgr(ctx, backend.DefaultStateName)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -243,7 +243,7 @@ func (b *Backend) configure(ctx context.Context) error {
return nil return nil
} }
func (b *Backend) StateMgr(name string) (statemgr.Full, error) { func (b *Backend) StateMgr(ctx context.Context, name string) (statemgr.Full, error) {
if name != backend.DefaultStateName { if name != backend.DefaultStateName {
return nil, backend.ErrWorkspacesNotSupported return nil, backend.ErrWorkspacesNotSupported
} }

View File

@ -279,8 +279,10 @@ func TestMTLSServer_NoCertFails(t *testing.T) {
t.Fatal("nil backend") t.Fatal("nil backend")
} }
ctx := context.Background()
// Now get a state manager and check that it fails to refresh the state // Now get a state manager and check that it fails to refresh the state
sm, err := b.StateMgr(backend.DefaultStateName) sm, err := b.StateMgr(ctx, backend.DefaultStateName)
if err != nil { if err != nil {
t.Fatalf("unexpected error fetching StateMgr with %s: %v", backend.DefaultStateName, err) t.Fatalf("unexpected error fetching StateMgr with %s: %v", backend.DefaultStateName, err)
} }
@ -350,8 +352,10 @@ func TestMTLSServer_WithCertPasses(t *testing.T) {
t.Fatal("nil backend") t.Fatal("nil backend")
} }
ctx := context.Background()
// Now get a state manager, fetch the state, and ensure that the "foo" output is not set // Now get a state manager, fetch the state, and ensure that the "foo" output is not set
sm, err := b.StateMgr(backend.DefaultStateName) sm, err := b.StateMgr(ctx, backend.DefaultStateName)
if err != nil { if err != nil {
t.Fatalf("unexpected error fetching StateMgr with %s: %v", backend.DefaultStateName, err) t.Fatalf("unexpected error fetching StateMgr with %s: %v", backend.DefaultStateName, err)
} }

View File

@ -116,7 +116,7 @@ func (b *Backend) DeleteWorkspace(name string, _ bool) error {
return nil return nil
} }
func (b *Backend) StateMgr(name string) (statemgr.Full, error) { func (b *Backend) StateMgr(ctx context.Context, name string) (statemgr.Full, error) {
states.Lock() states.Lock()
defer states.Unlock() defer states.Unlock()

View File

@ -4,6 +4,7 @@
package inmem package inmem
import ( import (
"context"
"flag" "flag"
"os" "os"
"testing" "testing"
@ -36,7 +37,9 @@ func TestBackendConfig(t *testing.T) {
b := backend.TestBackendConfig(t, New(), backend.TestWrapConfig(config)).(*Backend) b := backend.TestBackendConfig(t, New(), backend.TestWrapConfig(config)).(*Backend)
s, err := b.StateMgr(backend.DefaultStateName) ctx := context.Background()
s, err := b.StateMgr(ctx, backend.DefaultStateName)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -72,8 +75,10 @@ func TestRemoteState(t *testing.T) {
workspace := "workspace" workspace := "workspace"
ctx := context.Background()
// create a new workspace in this backend // create a new workspace in this backend
s, err := b.StateMgr(workspace) s, err := b.StateMgr(ctx, workspace)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }

View File

@ -4,6 +4,7 @@
package inmem package inmem
import ( import (
"context"
"testing" "testing"
"github.com/hashicorp/hcl/v2" "github.com/hashicorp/hcl/v2"
@ -20,7 +21,9 @@ func TestRemoteClient(t *testing.T) {
defer Reset() defer Reset()
b := backend.TestBackendConfig(t, New(), hcl.EmptyBody()) b := backend.TestBackendConfig(t, New(), hcl.EmptyBody())
s, err := b.StateMgr(backend.DefaultStateName) ctx := context.Background()
s, err := b.StateMgr(ctx, backend.DefaultStateName)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -30,7 +33,9 @@ func TestRemoteClient(t *testing.T) {
func TestInmemLocks(t *testing.T) { func TestInmemLocks(t *testing.T) {
defer Reset() defer Reset()
s, err := backend.TestBackendConfig(t, New(), hcl.EmptyBody()).StateMgr(backend.DefaultStateName)
ctx := context.Background()
s, err := backend.TestBackendConfig(t, New(), hcl.EmptyBody()).StateMgr(ctx, backend.DefaultStateName)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }

View File

@ -76,7 +76,7 @@ func (b *Backend) DeleteWorkspace(name string, _ bool) error {
return client.Delete() return client.Delete()
} }
func (b *Backend) StateMgr(name string) (statemgr.Full, error) { func (b *Backend) StateMgr(ctx context.Context, name string) (statemgr.Full, error) {
c, err := b.remoteClient(name) c, err := b.remoteClient(name)
if err != nil { if err != nil {
return nil, err return nil, err

View File

@ -89,7 +89,9 @@ func TestBackendLocksSoak(t *testing.T) {
"secret_suffix": secretSuffix, "secret_suffix": secretSuffix,
})) }))
s, err := b.StateMgr(backend.DefaultStateName) ctx := context.Background()
s, err := b.StateMgr(ctx, backend.DefaultStateName)
if err != nil { if err != nil {
t.Fatalf("Error creating state manager: %v", err) t.Fatalf("Error creating state manager: %v", err)
} }

View File

@ -4,6 +4,7 @@
package kubernetes package kubernetes
import ( import (
"context"
"testing" "testing"
"github.com/opentofu/opentofu/internal/backend" "github.com/opentofu/opentofu/internal/backend"
@ -24,7 +25,9 @@ func TestRemoteClient(t *testing.T) {
"secret_suffix": secretSuffix, "secret_suffix": secretSuffix,
})) }))
state, err := b.StateMgr(backend.DefaultStateName) ctx := context.Background()
state, err := b.StateMgr(ctx, backend.DefaultStateName)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -44,12 +47,14 @@ func TestRemoteClientLocks(t *testing.T) {
"secret_suffix": secretSuffix, "secret_suffix": secretSuffix,
})) }))
s1, err := b1.StateMgr(backend.DefaultStateName) ctx := context.Background()
s1, err := b1.StateMgr(ctx, backend.DefaultStateName)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
s2, err := b2.StateMgr(backend.DefaultStateName) s2, err := b2.StateMgr(ctx, backend.DefaultStateName)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -69,8 +74,10 @@ func TestForceUnlock(t *testing.T) {
"secret_suffix": secretSuffix, "secret_suffix": secretSuffix,
})) }))
ctx := context.Background()
// first test with default // first test with default
s1, err := b1.StateMgr(backend.DefaultStateName) s1, err := b1.StateMgr(ctx, backend.DefaultStateName)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -85,7 +92,7 @@ func TestForceUnlock(t *testing.T) {
} }
// s1 is now locked, get the same state through s2 and unlock it // s1 is now locked, get the same state through s2 and unlock it
s2, err := b2.StateMgr(backend.DefaultStateName) s2, err := b2.StateMgr(ctx, backend.DefaultStateName)
if err != nil { if err != nil {
t.Fatal("failed to get default state to force unlock:", err) t.Fatal("failed to get default state to force unlock:", err)
} }
@ -96,7 +103,7 @@ func TestForceUnlock(t *testing.T) {
// now try the same thing with a named state // now try the same thing with a named state
// first test with default // first test with default
s1, err = b1.StateMgr("test") s1, err = b1.StateMgr(ctx, "test")
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -111,7 +118,7 @@ func TestForceUnlock(t *testing.T) {
} }
// s1 is now locked, get the same state through s2 and unlock it // s1 is now locked, get the same state through s2 and unlock it
s2, err = b2.StateMgr("test") s2, err = b2.StateMgr(ctx, "test")
if err != nil { if err != nil {
t.Fatal("failed to get named state to force unlock:", err) t.Fatal("failed to get named state to force unlock:", err)
} }

View File

@ -4,6 +4,7 @@
package oss package oss
import ( import (
"context"
"errors" "errors"
"fmt" "fmt"
"log" "log"
@ -111,7 +112,7 @@ func (b *Backend) DeleteWorkspace(name string, _ bool) error {
return client.Delete() return client.Delete()
} }
func (b *Backend) StateMgr(name string) (statemgr.Full, error) { func (b *Backend) StateMgr(ctx context.Context, name string) (statemgr.Full, error) {
client, err := b.remoteClient(name) client, err := b.remoteClient(name)
if err != nil { if err != nil {
return nil, err return nil, err

View File

@ -4,6 +4,7 @@
package oss package oss
import ( import (
"context"
"fmt" "fmt"
"strings" "strings"
"testing" "testing"
@ -40,7 +41,9 @@ func TestRemoteClient(t *testing.T) {
createOSSBucket(t, b.ossClient, bucketName) createOSSBucket(t, b.ossClient, bucketName)
defer deleteOSSBucket(t, b.ossClient, bucketName) defer deleteOSSBucket(t, b.ossClient, bucketName)
state, err := b.StateMgr(backend.DefaultStateName) ctx := context.Background()
state, err := b.StateMgr(ctx, backend.DefaultStateName)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -75,12 +78,14 @@ func TestRemoteClientLocks(t *testing.T) {
createTablestoreTable(t, b1.otsClient, tableName) createTablestoreTable(t, b1.otsClient, tableName)
defer deleteTablestoreTable(t, b1.otsClient, tableName) defer deleteTablestoreTable(t, b1.otsClient, tableName)
s1, err := b1.StateMgr(backend.DefaultStateName) ctx := context.Background()
s1, err := b1.StateMgr(ctx, backend.DefaultStateName)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
s2, err := b2.StateMgr(backend.DefaultStateName) s2, err := b2.StateMgr(ctx, backend.DefaultStateName)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -116,7 +121,9 @@ func TestRemoteClientLocks_multipleStates(t *testing.T) {
createTablestoreTable(t, b1.otsClient, tableName) createTablestoreTable(t, b1.otsClient, tableName)
defer deleteTablestoreTable(t, b1.otsClient, tableName) defer deleteTablestoreTable(t, b1.otsClient, tableName)
s1, err := b1.StateMgr("s1") ctx := context.Background()
s1, err := b1.StateMgr(ctx, "s1")
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -125,7 +132,7 @@ func TestRemoteClientLocks_multipleStates(t *testing.T) {
} }
// s1 is now locked, s2 should not be locked as it's a different state file // s1 is now locked, s2 should not be locked as it's a different state file
s2, err := b2.StateMgr("s2") s2, err := b2.StateMgr(ctx, "s2")
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -162,8 +169,10 @@ func TestRemoteForceUnlock(t *testing.T) {
createTablestoreTable(t, b1.otsClient, tableName) createTablestoreTable(t, b1.otsClient, tableName)
defer deleteTablestoreTable(t, b1.otsClient, tableName) defer deleteTablestoreTable(t, b1.otsClient, tableName)
ctx := context.Background()
// first test with default // first test with default
s1, err := b1.StateMgr(backend.DefaultStateName) s1, err := b1.StateMgr(ctx, backend.DefaultStateName)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -178,7 +187,7 @@ func TestRemoteForceUnlock(t *testing.T) {
} }
// s1 is now locked, get the same state through s2 and unlock it // s1 is now locked, get the same state through s2 and unlock it
s2, err := b2.StateMgr(backend.DefaultStateName) s2, err := b2.StateMgr(ctx, backend.DefaultStateName)
if err != nil { if err != nil {
t.Fatal("failed to get default state to force unlock:", err) t.Fatal("failed to get default state to force unlock:", err)
} }
@ -189,7 +198,7 @@ func TestRemoteForceUnlock(t *testing.T) {
// now try the same thing with a named state // now try the same thing with a named state
// first test with default // first test with default
s1, err = b1.StateMgr("test") s1, err = b1.StateMgr(ctx, "test")
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -204,7 +213,7 @@ func TestRemoteForceUnlock(t *testing.T) {
} }
// s1 is now locked, get the same state through s2 and unlock it // s1 is now locked, get the same state through s2 and unlock it
s2, err = b2.StateMgr("test") s2, err = b2.StateMgr(ctx, "test")
if err != nil { if err != nil {
t.Fatal("failed to get named state to force unlock:", err) t.Fatal("failed to get named state to force unlock:", err)
} }
@ -233,7 +242,9 @@ func TestRemoteClient_clientMD5(t *testing.T) {
createTablestoreTable(t, b.otsClient, tableName) createTablestoreTable(t, b.otsClient, tableName)
defer deleteTablestoreTable(t, b.otsClient, tableName) defer deleteTablestoreTable(t, b.otsClient, tableName)
s, err := b.StateMgr(backend.DefaultStateName) ctx := context.Background()
s, err := b.StateMgr(ctx, backend.DefaultStateName)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -283,7 +294,9 @@ func TestRemoteClient_stateChecksum(t *testing.T) {
createTablestoreTable(t, b1.otsClient, tableName) createTablestoreTable(t, b1.otsClient, tableName)
defer deleteTablestoreTable(t, b1.otsClient, tableName) defer deleteTablestoreTable(t, b1.otsClient, tableName)
s1, err := b1.StateMgr(backend.DefaultStateName) ctx := context.Background()
s1, err := b1.StateMgr(ctx, backend.DefaultStateName)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -308,7 +321,7 @@ func TestRemoteClient_stateChecksum(t *testing.T) {
"bucket": bucketName, "bucket": bucketName,
"prefix": path, "prefix": path,
})).(*Backend) })).(*Backend)
s2, err := b2.StateMgr(backend.DefaultStateName) s2, err := b2.StateMgr(ctx, backend.DefaultStateName)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }

View File

@ -4,6 +4,7 @@
package pg package pg
import ( import (
"context"
"fmt" "fmt"
"github.com/opentofu/opentofu/internal/backend" "github.com/opentofu/opentofu/internal/backend"
@ -52,7 +53,7 @@ func (b *Backend) DeleteWorkspace(name string, _ bool) error {
return nil return nil
} }
func (b *Backend) StateMgr(name string) (statemgr.Full, error) { func (b *Backend) StateMgr(ctx context.Context, name string) (statemgr.Full, error) {
// Build the state client // Build the state client
var stateMgr statemgr.Full = &remote.State{ var stateMgr statemgr.Full = &remote.State{
Client: &RemoteClient{ Client: &RemoteClient{

View File

@ -200,12 +200,12 @@ func TestBackendConfig(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
_, err = b.StateMgr(backend.DefaultStateName) _, err = b.StateMgr(ctx, backend.DefaultStateName)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
s, err := b.StateMgr(backend.DefaultStateName) s, err := b.StateMgr(ctx, backend.DefaultStateName)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -341,12 +341,14 @@ func TestBackendConfigSkipOptions(t *testing.T) {
} }
} }
_, err = b.StateMgr(backend.DefaultStateName) ctx := context.Background()
_, err = b.StateMgr(ctx, backend.DefaultStateName)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
s, err := b.StateMgr(backend.DefaultStateName) s, err := b.StateMgr(ctx, backend.DefaultStateName)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -448,7 +450,10 @@ func TestBackendConcurrentLock(t *testing.T) {
if b == nil { if b == nil {
t.Fatal("Backend could not be configured") t.Fatal("Backend could not be configured")
} }
stateMgr, err := b.StateMgr(backend.DefaultStateName)
ctx := context.Background()
stateMgr, err := b.StateMgr(ctx, backend.DefaultStateName)
if err != nil { if err != nil {
t.Fatalf("Failed to get the state manager: %v", err) t.Fatalf("Failed to get the state manager: %v", err)
} }

View File

@ -7,6 +7,7 @@ package pg
// TF_ACC=1 GO111MODULE=on go test -v -mod=vendor -timeout=2m -parallel=4 github.com/opentofu/opentofu/backend/remote-state/pg // TF_ACC=1 GO111MODULE=on go test -v -mod=vendor -timeout=2m -parallel=4 github.com/opentofu/opentofu/backend/remote-state/pg
import ( import (
"context"
"database/sql" "database/sql"
"fmt" "fmt"
"testing" "testing"
@ -40,7 +41,9 @@ func TestRemoteClient(t *testing.T) {
t.Fatal("Backend could not be configured") t.Fatal("Backend could not be configured")
} }
s, err := b.StateMgr(backend.DefaultStateName) ctx := context.Background()
s, err := b.StateMgr(ctx, backend.DefaultStateName)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -63,14 +66,16 @@ func TestRemoteLocks(t *testing.T) {
"schema_name": schemaName, "schema_name": schemaName,
}) })
ctx := context.Background()
b1 := backend.TestBackendConfig(t, New(), config).(*Backend) b1 := backend.TestBackendConfig(t, New(), config).(*Backend)
s1, err := b1.StateMgr(backend.DefaultStateName) s1, err := b1.StateMgr(ctx, backend.DefaultStateName)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
b2 := backend.TestBackendConfig(t, New(), config).(*Backend) b2 := backend.TestBackendConfig(t, New(), config).(*Backend)
s2, err := b2.StateMgr(backend.DefaultStateName) s2, err := b2.StateMgr(ctx, backend.DefaultStateName)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }

View File

@ -136,7 +136,7 @@ func (b *Backend) remoteClient(name string) (*RemoteClient, error) {
return client, nil return client, nil
} }
func (b *Backend) StateMgr(name string) (statemgr.Full, error) { func (b *Backend) StateMgr(ctx context.Context, name string) (statemgr.Full, error) {
client, err := b.remoteClient(name) client, err := b.remoteClient(name)
if err != nil { if err != nil {
return nil, err return nil, err

View File

@ -1112,7 +1112,7 @@ func TestBackendExtraPaths(t *testing.T) {
} }
// fetch that state again, which should produce a new lineage // fetch that state again, which should produce a new lineage
s2Mgr, err := b.StateMgr("s2") s2Mgr, err := b.StateMgr(ctx, "s2")
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -1136,7 +1136,7 @@ func TestBackendExtraPaths(t *testing.T) {
} }
// make sure s2 is OK // make sure s2 is OK
s2Mgr, err = b.StateMgr("s2") s2Mgr, err = b.StateMgr(ctx, "s2")
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -1170,7 +1170,7 @@ func TestBackendPrefixInWorkspace(t *testing.T) {
defer deleteS3Bucket(ctx, t, b.s3Client, bucketName) defer deleteS3Bucket(ctx, t, b.s3Client, bucketName)
// get a state that contains the prefix as a substring // get a state that contains the prefix as a substring
sMgr, err := b.StateMgr("env-1") sMgr, err := b.StateMgr(ctx, "env-1")
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }

View File

@ -34,11 +34,11 @@ func TestRemoteClient(t *testing.T) {
"encrypt": true, "encrypt": true,
})).(*Backend) })).(*Backend)
ctx := context.TODO() ctx := context.Background()
createS3Bucket(ctx, t, b.s3Client, bucketName, b.awsConfig.Region) createS3Bucket(ctx, t, b.s3Client, bucketName, b.awsConfig.Region)
defer deleteS3Bucket(ctx, t, b.s3Client, bucketName) defer deleteS3Bucket(ctx, t, b.s3Client, bucketName)
state, err := b.StateMgr(backend.DefaultStateName) state, err := b.StateMgr(ctx, backend.DefaultStateName)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -71,12 +71,12 @@ func TestRemoteClientLocks(t *testing.T) {
createDynamoDBTable(ctx, t, b1.dynClient, bucketName) createDynamoDBTable(ctx, t, b1.dynClient, bucketName)
defer deleteDynamoDBTable(ctx, t, b1.dynClient, bucketName) defer deleteDynamoDBTable(ctx, t, b1.dynClient, bucketName)
s1, err := b1.StateMgr(backend.DefaultStateName) s1, err := b1.StateMgr(ctx, backend.DefaultStateName)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
s2, err := b2.StateMgr(backend.DefaultStateName) s2, err := b2.StateMgr(ctx, backend.DefaultStateName)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -111,7 +111,7 @@ func TestForceUnlock(t *testing.T) {
defer deleteDynamoDBTable(ctx, t, b1.dynClient, bucketName) defer deleteDynamoDBTable(ctx, t, b1.dynClient, bucketName)
// first test with default // first test with default
s1, err := b1.StateMgr(backend.DefaultStateName) s1, err := b1.StateMgr(ctx, backend.DefaultStateName)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -126,7 +126,7 @@ func TestForceUnlock(t *testing.T) {
} }
// s1 is now locked, get the same state through s2 and unlock it // s1 is now locked, get the same state through s2 and unlock it
s2, err := b2.StateMgr(backend.DefaultStateName) s2, err := b2.StateMgr(ctx, backend.DefaultStateName)
if err != nil { if err != nil {
t.Fatal("failed to get default state to force unlock:", err) t.Fatal("failed to get default state to force unlock:", err)
} }
@ -137,7 +137,7 @@ func TestForceUnlock(t *testing.T) {
// now try the same thing with a named state // now try the same thing with a named state
// first test with default // first test with default
s1, err = b1.StateMgr("test") s1, err = b1.StateMgr(ctx, "test")
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -152,7 +152,7 @@ func TestForceUnlock(t *testing.T) {
} }
// s1 is now locked, get the same state through s2 and unlock it // s1 is now locked, get the same state through s2 and unlock it
s2, err = b2.StateMgr("test") s2, err = b2.StateMgr(ctx, "test")
if err != nil { if err != nil {
t.Fatal("failed to get named state to force unlock:", err) t.Fatal("failed to get named state to force unlock:", err)
} }
@ -180,7 +180,7 @@ func TestRemoteClient_clientMD5(t *testing.T) {
createDynamoDBTable(ctx, t, b.dynClient, bucketName) createDynamoDBTable(ctx, t, b.dynClient, bucketName)
defer deleteDynamoDBTable(ctx, t, b.dynClient, bucketName) defer deleteDynamoDBTable(ctx, t, b.dynClient, bucketName)
s, err := b.StateMgr(backend.DefaultStateName) s, err := b.StateMgr(ctx, backend.DefaultStateName)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -229,7 +229,7 @@ func TestRemoteClient_stateChecksum(t *testing.T) {
createDynamoDBTable(ctx, t, b1.dynClient, bucketName) createDynamoDBTable(ctx, t, b1.dynClient, bucketName)
defer deleteDynamoDBTable(ctx, t, b1.dynClient, bucketName) defer deleteDynamoDBTable(ctx, t, b1.dynClient, bucketName)
s1, err := b1.StateMgr(backend.DefaultStateName) s1, err := b1.StateMgr(ctx, backend.DefaultStateName)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -254,7 +254,7 @@ func TestRemoteClient_stateChecksum(t *testing.T) {
"bucket": bucketName, "bucket": bucketName,
"key": keyName, "key": keyName,
})).(*Backend) })).(*Backend)
s2, err := b2.StateMgr(backend.DefaultStateName) s2, err := b2.StateMgr(ctx, backend.DefaultStateName)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }

View File

@ -637,7 +637,7 @@ func (b *Remote) DeleteWorkspace(name string, _ bool) error {
} }
// StateMgr implements backend.Enhanced. // StateMgr implements backend.Enhanced.
func (b *Remote) StateMgr(name string) (statemgr.Full, error) { func (b *Remote) StateMgr(ctx context.Context, name string) (statemgr.Full, error) {
if b.workspace == "" && name == backend.DefaultStateName { if b.workspace == "" && name == backend.DefaultStateName {
return nil, backend.ErrDefaultWorkspaceNotSupported return nil, backend.ErrDefaultWorkspaceNotSupported
} }
@ -653,7 +653,7 @@ func (b *Remote) StateMgr(name string) (statemgr.Full, error) {
name = b.prefix + name name = b.prefix + name
} }
workspace, err := b.client.Workspaces.Read(context.Background(), b.organization, name) workspace, err := b.client.Workspaces.Read(ctx, b.organization, name)
if err != nil && err != tfe.ErrResourceNotFound { if err != nil && err != tfe.ErrResourceNotFound {
return nil, fmt.Errorf("Failed to retrieve workspace %s: %w", name, err) return nil, fmt.Errorf("Failed to retrieve workspace %s: %w", name, err)
} }
@ -669,7 +669,7 @@ func (b *Remote) StateMgr(name string) (statemgr.Full, error) {
options.TerraformVersion = tfe.String(tfversion.String()) options.TerraformVersion = tfe.String(tfversion.String())
} }
workspace, err = b.client.Workspaces.Create(context.Background(), b.organization, options) workspace, err = b.client.Workspaces.Create(ctx, b.organization, options)
if err != nil { if err != nil {
return nil, fmt.Errorf("Error creating workspace %s: %w", name, err) return nil, fmt.Errorf("Error creating workspace %s: %w", name, err)
} }

View File

@ -81,7 +81,9 @@ func TestRemote_applyBasic(t *testing.T) {
op.UIOut = b.CLI op.UIOut = b.CLI
op.Workspace = backend.DefaultStateName op.Workspace = backend.DefaultStateName
run, err := b.Operation(context.Background(), op) ctx := context.Background()
run, err := b.Operation(ctx, op)
if err != nil { if err != nil {
t.Fatalf("error starting operation: %v", err) t.Fatalf("error starting operation: %v", err)
} }
@ -109,7 +111,7 @@ func TestRemote_applyBasic(t *testing.T) {
t.Fatalf("expected apply summery in output: %s", output) t.Fatalf("expected apply summery in output: %s", output)
} }
stateMgr, _ := b.StateMgr(backend.DefaultStateName) stateMgr, _ := b.StateMgr(ctx, backend.DefaultStateName)
// An error suggests that the state was not unlocked after apply // An error suggests that the state was not unlocked after apply
if _, err := stateMgr.Lock(statemgr.NewLockInfo()); err != nil { if _, err := stateMgr.Lock(statemgr.NewLockInfo()); err != nil {
t.Fatalf("unexpected error locking state after apply: %s", err.Error()) t.Fatalf("unexpected error locking state after apply: %s", err.Error())
@ -126,7 +128,9 @@ func TestRemote_applyCanceled(t *testing.T) {
op.Workspace = backend.DefaultStateName op.Workspace = backend.DefaultStateName
run, err := b.Operation(context.Background(), op) ctx := context.Background()
run, err := b.Operation(ctx, op)
if err != nil { if err != nil {
t.Fatalf("error starting operation: %v", err) t.Fatalf("error starting operation: %v", err)
} }
@ -139,7 +143,7 @@ func TestRemote_applyCanceled(t *testing.T) {
t.Fatal("expected apply operation to fail") t.Fatal("expected apply operation to fail")
} }
stateMgr, _ := b.StateMgr(backend.DefaultStateName) stateMgr, _ := b.StateMgr(ctx, backend.DefaultStateName)
if _, err := stateMgr.Lock(statemgr.NewLockInfo()); err != nil { if _, err := stateMgr.Lock(statemgr.NewLockInfo()); err != nil {
t.Fatalf("unexpected error locking state after cancelling apply: %s", err.Error()) t.Fatalf("unexpected error locking state after cancelling apply: %s", err.Error())
} }
@ -609,7 +613,8 @@ func TestRemote_applyNoConfig(t *testing.T) {
op.Workspace = backend.DefaultStateName op.Workspace = backend.DefaultStateName
run, err := b.Operation(context.Background(), op) ctx := context.Background()
run, err := b.Operation(ctx, op)
if err != nil { if err != nil {
t.Fatalf("error starting operation: %v", err) t.Fatalf("error starting operation: %v", err)
} }
@ -628,7 +633,7 @@ func TestRemote_applyNoConfig(t *testing.T) {
t.Fatalf("expected configuration files error, got: %v", errOutput) t.Fatalf("expected configuration files error, got: %v", errOutput)
} }
stateMgr, _ := b.StateMgr(backend.DefaultStateName) stateMgr, _ := b.StateMgr(ctx, backend.DefaultStateName)
// An error suggests that the state was not unlocked after apply // An error suggests that the state was not unlocked after apply
if _, err := stateMgr.Lock(statemgr.NewLockInfo()); err != nil { if _, err := stateMgr.Lock(statemgr.NewLockInfo()); err != nil {
t.Fatalf("unexpected error locking state after failed apply: %s", err.Error()) t.Fatalf("unexpected error locking state after failed apply: %s", err.Error())

View File

@ -35,9 +35,11 @@ func (b *Remote) LocalRun(op *backend.Operation) (*backend.LocalRun, statemgr.Fu
// Get the remote workspace name. // Get the remote workspace name.
remoteWorkspaceName := b.getRemoteWorkspaceName(op.Workspace) remoteWorkspaceName := b.getRemoteWorkspaceName(op.Workspace)
ctx := context.TODO()
// Get the latest state. // Get the latest state.
log.Printf("[TRACE] backend/remote: requesting state manager for workspace %q", remoteWorkspaceName) log.Printf("[TRACE] backend/remote: requesting state manager for workspace %q", remoteWorkspaceName)
stateMgr, err := b.StateMgr(op.Workspace) stateMgr, err := b.StateMgr(ctx, op.Workspace)
if err != nil { if err != nil {
diags = diags.Append(fmt.Errorf("error loading state: %w", err)) diags = diags.Append(fmt.Errorf("error loading state: %w", err))
return nil, nil, diags return nil, nil, diags

View File

@ -210,7 +210,10 @@ func TestRemoteContextWithVars(t *testing.T) {
key := "key" key := "key"
v.Key = &key v.Key = &key
} }
b.client.Variables.Create(context.TODO(), workspaceID, *v)
ctx := context.Background()
b.client.Variables.Create(ctx, workspaceID, *v)
_, _, diags := b.LocalRun(op) _, _, diags := b.LocalRun(op)
@ -224,7 +227,7 @@ func TestRemoteContextWithVars(t *testing.T) {
} }
// When Context() returns an error, it should unlock the state, // When Context() returns an error, it should unlock the state,
// so re-locking it is expected to succeed. // so re-locking it is expected to succeed.
stateMgr, _ := b.StateMgr(backend.DefaultStateName) stateMgr, _ := b.StateMgr(ctx, backend.DefaultStateName)
if _, err := stateMgr.Lock(statemgr.NewLockInfo()); err != nil { if _, err := stateMgr.Lock(statemgr.NewLockInfo()); err != nil {
t.Fatalf("unexpected error locking state: %s", err.Error()) t.Fatalf("unexpected error locking state: %s", err.Error())
} }
@ -233,7 +236,7 @@ func TestRemoteContextWithVars(t *testing.T) {
t.Fatalf("unexpected error\ngot: %s\nwant: <no error>", diags.Err().Error()) t.Fatalf("unexpected error\ngot: %s\nwant: <no error>", diags.Err().Error())
} }
// When Context() succeeds, this should fail w/ "workspace already locked" // When Context() succeeds, this should fail w/ "workspace already locked"
stateMgr, _ := b.StateMgr(backend.DefaultStateName) stateMgr, _ := b.StateMgr(ctx, backend.DefaultStateName)
if _, err := stateMgr.Lock(statemgr.NewLockInfo()); err == nil { if _, err := stateMgr.Lock(statemgr.NewLockInfo()); err == nil {
t.Fatal("unexpected success locking state after Context") t.Fatal("unexpected success locking state after Context")
} }
@ -429,8 +432,10 @@ func TestRemoteVariablesDoNotOverride(t *testing.T) {
Variables: test.localVariables, Variables: test.localVariables,
} }
ctx := context.Background()
for _, v := range test.remoteVariables { for _, v := range test.remoteVariables {
b.client.Variables.Create(context.TODO(), workspaceID, *v) b.client.Variables.Create(ctx, workspaceID, *v)
} }
lr, _, diags := b.LocalRun(op) lr, _, diags := b.LocalRun(op)
@ -439,7 +444,7 @@ func TestRemoteVariablesDoNotOverride(t *testing.T) {
t.Fatalf("unexpected error\ngot: %s\nwant: <no error>", diags.Err().Error()) t.Fatalf("unexpected error\ngot: %s\nwant: <no error>", diags.Err().Error())
} }
// When Context() succeeds, this should fail w/ "workspace already locked" // When Context() succeeds, this should fail w/ "workspace already locked"
stateMgr, _ := b.StateMgr(backend.DefaultStateName) stateMgr, _ := b.StateMgr(ctx, backend.DefaultStateName)
if _, err := stateMgr.Lock(statemgr.NewLockInfo()); err == nil { if _, err := stateMgr.Lock(statemgr.NewLockInfo()); err == nil {
t.Fatal("unexpected success locking state after Context") t.Fatal("unexpected success locking state after Context")
} }

View File

@ -94,7 +94,9 @@ func TestRemote_planBasic(t *testing.T) {
t.Fatalf("expected plan summary in output: %s", output) t.Fatalf("expected plan summary in output: %s", output)
} }
stateMgr, _ := b.StateMgr(backend.DefaultStateName) ctx := context.Background()
stateMgr, _ := b.StateMgr(ctx, backend.DefaultStateName)
// An error suggests that the state was not unlocked after the operation finished // 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(statemgr.NewLockInfo()); err != nil {
t.Fatalf("unexpected error locking state after successful plan: %s", err.Error()) t.Fatalf("unexpected error locking state after successful plan: %s", err.Error())
@ -124,7 +126,9 @@ func TestRemote_planCanceled(t *testing.T) {
t.Fatal("expected plan operation to fail") t.Fatal("expected plan operation to fail")
} }
stateMgr, _ := b.StateMgr(backend.DefaultStateName) ctx := context.Background()
stateMgr, _ := b.StateMgr(ctx, backend.DefaultStateName)
// An error suggests that the state was not unlocked after the operation finished // 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(statemgr.NewLockInfo()); err != nil {
t.Fatalf("unexpected error locking state after cancelled plan: %s", err.Error()) t.Fatalf("unexpected error locking state after cancelled plan: %s", err.Error())

View File

@ -5,6 +5,7 @@ package remote
import ( import (
"bytes" "bytes"
"context"
"os" "os"
"testing" "testing"
@ -28,12 +29,14 @@ func TestRemoteClient_stateLock(t *testing.T) {
b, bCleanup := testBackendDefault(t) b, bCleanup := testBackendDefault(t)
defer bCleanup() defer bCleanup()
s1, err := b.StateMgr(backend.DefaultStateName) ctx := context.Background()
s1, err := b.StateMgr(ctx, backend.DefaultStateName)
if err != nil { if err != nil {
t.Fatalf("expected no error, got %v", err) t.Fatalf("expected no error, got %v", err)
} }
s2, err := b.StateMgr(backend.DefaultStateName) s2, err := b.StateMgr(ctx, backend.DefaultStateName)
if err != nil { if err != nil {
t.Fatalf("expected no error, got %v", err) t.Fatalf("expected no error, got %v", err)
} }

View File

@ -273,11 +273,13 @@ func TestRemote_addAndRemoveWorkspacesDefault(t *testing.T) {
t.Fatalf("expected error %v, got %v", backend.ErrWorkspacesNotSupported, err) t.Fatalf("expected error %v, got %v", backend.ErrWorkspacesNotSupported, err)
} }
if _, err := b.StateMgr(backend.DefaultStateName); err != nil { ctx := context.Background()
if _, err := b.StateMgr(ctx, backend.DefaultStateName); err != nil {
t.Fatalf("expected no error, got %v", err) t.Fatalf("expected no error, got %v", err)
} }
if _, err := b.StateMgr("prod"); err != backend.ErrWorkspacesNotSupported { if _, err := b.StateMgr(ctx, "prod"); err != backend.ErrWorkspacesNotSupported {
t.Fatalf("expected error %v, got %v", backend.ErrWorkspacesNotSupported, err) t.Fatalf("expected error %v, got %v", backend.ErrWorkspacesNotSupported, err)
} }
@ -304,12 +306,14 @@ func TestRemote_addAndRemoveWorkspacesNoDefault(t *testing.T) {
t.Fatalf("expected states %#+v, got %#+v", expectedWorkspaces, states) t.Fatalf("expected states %#+v, got %#+v", expectedWorkspaces, states)
} }
if _, err := b.StateMgr(backend.DefaultStateName); err != backend.ErrDefaultWorkspaceNotSupported { ctx := context.Background()
if _, err := b.StateMgr(ctx, backend.DefaultStateName); err != backend.ErrDefaultWorkspaceNotSupported {
t.Fatalf("expected error %v, got %v", backend.ErrDefaultWorkspaceNotSupported, err) t.Fatalf("expected error %v, got %v", backend.ErrDefaultWorkspaceNotSupported, err)
} }
expectedA := "test_A" expectedA := "test_A"
if _, err := b.StateMgr(expectedA); err != nil { if _, err := b.StateMgr(ctx, expectedA); err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -324,7 +328,7 @@ func TestRemote_addAndRemoveWorkspacesNoDefault(t *testing.T) {
} }
expectedB := "test_B" expectedB := "test_B"
if _, err := b.StateMgr(expectedB); err != nil { if _, err := b.StateMgr(ctx, expectedB); err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -510,8 +514,10 @@ func TestRemote_StateMgr_versionCheck(t *testing.T) {
t.Fatalf("error: %v", err) t.Fatalf("error: %v", err)
} }
ctx := context.Background()
// This should succeed // This should succeed
if _, err := b.StateMgr(backend.DefaultStateName); err != nil { if _, err := b.StateMgr(ctx, backend.DefaultStateName); err != nil {
t.Fatalf("expected no error, got %v", err) t.Fatalf("expected no error, got %v", err)
} }
@ -529,7 +535,7 @@ func TestRemote_StateMgr_versionCheck(t *testing.T) {
// This should fail // This should fail
want := `Remote workspace OpenTofu version "0.13.5" does not match local OpenTofu version "0.14.0"` want := `Remote workspace OpenTofu version "0.13.5" does not match local OpenTofu version "0.14.0"`
if _, err := b.StateMgr(backend.DefaultStateName); err.Error() != want { if _, err := b.StateMgr(ctx, backend.DefaultStateName); err.Error() != want {
t.Fatalf("wrong error\n got: %v\nwant: %v", err.Error(), want) t.Fatalf("wrong error\n got: %v\nwant: %v", err.Error(), want)
} }
} }
@ -567,8 +573,10 @@ func TestRemote_StateMgr_versionCheckLatest(t *testing.T) {
t.Fatalf("error: %v", err) t.Fatalf("error: %v", err)
} }
ctx := context.Background()
// This should succeed despite not being a string match // This should succeed despite not being a string match
if _, err := b.StateMgr(backend.DefaultStateName); err != nil { if _, err := b.StateMgr(ctx, backend.DefaultStateName); err != nil {
t.Fatalf("expected no error, got %v", err) t.Fatalf("expected no error, got %v", err)
} }
} }

View File

@ -111,7 +111,9 @@ func testRemoteClient(t *testing.T) remote.Client {
b, bCleanup := testBackendDefault(t) b, bCleanup := testBackendDefault(t)
defer bCleanup() defer bCleanup()
raw, err := b.StateMgr(backend.DefaultStateName) ctx := context.Background()
raw, err := b.StateMgr(ctx, backend.DefaultStateName)
if err != nil { if err != nil {
t.Fatalf("error: %v", err) t.Fatalf("error: %v", err)
} }

View File

@ -81,8 +81,10 @@ func TestWrapConfig(raw map[string]interface{}) hcl.Body {
func TestBackendStates(t *testing.T, b Backend) { func TestBackendStates(t *testing.T, b Backend) {
t.Helper() t.Helper()
ctx := context.Background()
noDefault := false noDefault := false
if _, err := b.StateMgr(DefaultStateName); err != nil { if _, err := b.StateMgr(ctx, DefaultStateName); err != nil {
if err == ErrDefaultWorkspaceNotSupported { if err == ErrDefaultWorkspaceNotSupported {
noDefault = true noDefault = true
} else { } else {
@ -105,7 +107,7 @@ func TestBackendStates(t *testing.T, b Backend) {
} }
// Create a couple states // Create a couple states
foo, err := b.StateMgr("foo") foo, err := b.StateMgr(ctx, "foo")
if err != nil { if err != nil {
t.Fatalf("error: %s", err) t.Fatalf("error: %s", err)
} }
@ -116,7 +118,7 @@ func TestBackendStates(t *testing.T, b Backend) {
t.Fatalf("should be empty: %s", v) t.Fatalf("should be empty: %s", v)
} }
bar, err := b.StateMgr("bar") bar, err := b.StateMgr(ctx, "bar")
if err != nil { if err != nil {
t.Fatalf("error: %s", err) t.Fatalf("error: %s", err)
} }
@ -180,7 +182,7 @@ func TestBackendStates(t *testing.T, b Backend) {
} }
// fetch foo again from the backend // fetch foo again from the backend
foo, err = b.StateMgr("foo") foo, err = b.StateMgr(ctx, "foo")
if err != nil { if err != nil {
t.Fatal("error re-fetching state:", err) t.Fatal("error re-fetching state:", err)
} }
@ -193,7 +195,7 @@ func TestBackendStates(t *testing.T, b Backend) {
} }
// fetch the bar again from the backend // fetch the bar again from the backend
bar, err = b.StateMgr("bar") bar, err = b.StateMgr(ctx, "bar")
if err != nil { if err != nil {
t.Fatal("error re-fetching state:", err) t.Fatal("error re-fetching state:", err)
} }
@ -237,7 +239,7 @@ func TestBackendStates(t *testing.T, b Backend) {
// Create and delete the foo workspace again. // Create and delete the foo workspace again.
// Make sure that there are no leftover artifacts from a deleted state // Make sure that there are no leftover artifacts from a deleted state
// preventing re-creation. // preventing re-creation.
foo, err = b.StateMgr("foo") foo, err = b.StateMgr(ctx, "foo")
if err != nil { if err != nil {
t.Fatalf("error: %s", err) t.Fatalf("error: %s", err)
} }
@ -309,8 +311,10 @@ func testLocks(t *testing.T, b1, b2 Backend, testForceUnlock bool) {
func testLocksInWorkspace(t *testing.T, b1, b2 Backend, testForceUnlock bool, workspace string) { func testLocksInWorkspace(t *testing.T, b1, b2 Backend, testForceUnlock bool, workspace string) {
t.Helper() t.Helper()
ctx := context.Background()
// Get the default state for each // Get the default state for each
b1StateMgr, err := b1.StateMgr(DefaultStateName) b1StateMgr, err := b1.StateMgr(ctx, DefaultStateName)
if err != nil { if err != nil {
t.Fatalf("error: %s", err) t.Fatalf("error: %s", err)
} }
@ -326,7 +330,7 @@ func testLocksInWorkspace(t *testing.T, b1, b2 Backend, testForceUnlock bool, wo
t.Logf("TestBackend: testing state locking for %T", b1) t.Logf("TestBackend: testing state locking for %T", b1)
b2StateMgr, err := b2.StateMgr(DefaultStateName) b2StateMgr, err := b2.StateMgr(ctx, DefaultStateName)
if err != nil { if err != nil {
t.Fatalf("error: %s", err) t.Fatalf("error: %s", err)
} }
@ -354,7 +358,7 @@ func testLocksInWorkspace(t *testing.T, b1, b2 Backend, testForceUnlock bool, wo
// Make sure we can still get the statemgr.Full from another instance even // Make sure we can still get the statemgr.Full from another instance even
// when locked. This should only happen when a state is loaded via the // when locked. This should only happen when a state is loaded via the
// backend, and as a remote state. // backend, and as a remote state.
_, err = b2.StateMgr(DefaultStateName) _, err = b2.StateMgr(ctx, DefaultStateName)
if err != nil { if err != nil {
t.Errorf("failed to read locked state from another backend instance: %s", err) t.Errorf("failed to read locked state from another backend instance: %s", err)
} }

View File

@ -132,7 +132,7 @@ func dataSourceRemoteStateRead(d cty.Value) (cty.Value, tfdiags.Diagnostics) {
workspaceName = workspaceVal.AsString() workspaceName = workspaceVal.AsString()
} }
state, err := b.StateMgr(workspaceName) state, err := b.StateMgr(ctx, workspaceName)
if err != nil { if err != nil {
diags = diags.Append(tfdiags.AttributeValue( diags = diags.Append(tfdiags.AttributeValue(
tfdiags.Error, tfdiags.Error,

View File

@ -362,7 +362,7 @@ func (b backendFailsConfigure) Configure(_ context.Context, config cty.Value) tf
return diags return diags
} }
func (b backendFailsConfigure) StateMgr(workspace string) (statemgr.Full, error) { func (b backendFailsConfigure) StateMgr(context.Context, string) (statemgr.Full, error) {
return nil, fmt.Errorf("StateMgr not implemented") return nil, fmt.Errorf("StateMgr not implemented")
} }

View File

@ -616,7 +616,7 @@ func (b *Cloud) DeleteWorkspace(name string, force bool) error {
} }
// StateMgr implements backend.Enhanced. // StateMgr implements backend.Enhanced.
func (b *Cloud) StateMgr(name string) (statemgr.Full, error) { func (b *Cloud) StateMgr(ctx context.Context, name string) (statemgr.Full, error) {
var remoteTFVersion string var remoteTFVersion string
if name == backend.DefaultStateName { if name == backend.DefaultStateName {
@ -627,7 +627,7 @@ func (b *Cloud) StateMgr(name string) (statemgr.Full, error) {
return nil, backend.ErrWorkspacesNotSupported return nil, backend.ErrWorkspacesNotSupported
} }
workspace, err := b.client.Workspaces.Read(context.Background(), b.organization, name) workspace, err := b.client.Workspaces.Read(ctx, b.organization, name)
if err != nil && err != tfe.ErrResourceNotFound { if err != nil && err != tfe.ErrResourceNotFound {
return nil, fmt.Errorf("Failed to retrieve workspace %s: %w", name, err) return nil, fmt.Errorf("Failed to retrieve workspace %s: %w", name, err)
} }
@ -642,7 +642,7 @@ func (b *Cloud) StateMgr(name string) (statemgr.Full, error) {
listOpts := &tfe.ProjectListOptions{ listOpts := &tfe.ProjectListOptions{
Name: b.WorkspaceMapping.Project, Name: b.WorkspaceMapping.Project,
} }
projects, err := b.client.Projects.List(context.Background(), b.organization, listOpts) projects, err := b.client.Projects.List(ctx, b.organization, listOpts)
if err != nil && err != tfe.ErrResourceNotFound { if err != nil && err != tfe.ErrResourceNotFound {
// This is a failure to make an API request, fail to initialize // This is a failure to make an API request, fail to initialize
return nil, fmt.Errorf("Attempted to find configured project %s but was unable to.", b.WorkspaceMapping.Project) return nil, fmt.Errorf("Attempted to find configured project %s but was unable to.", b.WorkspaceMapping.Project)
@ -681,7 +681,7 @@ func (b *Cloud) StateMgr(name string) (statemgr.Full, error) {
} }
// didn't find project, create it instead // didn't find project, create it instead
log.Printf("[TRACE] cloud: Creating cloud backend project %s/%s", b.organization, b.WorkspaceMapping.Project) log.Printf("[TRACE] cloud: Creating cloud backend project %s/%s", b.organization, b.WorkspaceMapping.Project)
project, err := b.client.Projects.Create(context.Background(), b.organization, createOpts) project, err := b.client.Projects.Create(ctx, b.organization, createOpts)
if err != nil && err != tfe.ErrResourceNotFound { if err != nil && err != tfe.ErrResourceNotFound {
return nil, fmt.Errorf("failed to create project %s: %w", b.WorkspaceMapping.Project, err) return nil, fmt.Errorf("failed to create project %s: %w", b.WorkspaceMapping.Project, err)
} }
@ -692,7 +692,7 @@ func (b *Cloud) StateMgr(name string) (statemgr.Full, error) {
// Create a workspace // Create a workspace
log.Printf("[TRACE] cloud: Creating cloud backend workspace %s/%s", b.organization, name) log.Printf("[TRACE] cloud: Creating cloud backend workspace %s/%s", b.organization, name)
workspace, err = b.client.Workspaces.Create(context.Background(), b.organization, workspaceCreateOptions) workspace, err = b.client.Workspaces.Create(ctx, b.organization, workspaceCreateOptions)
if err != nil { if err != nil {
return nil, fmt.Errorf("error creating workspace %s: %w", name, err) return nil, fmt.Errorf("error creating workspace %s: %w", name, err)
} }
@ -705,7 +705,7 @@ func (b *Cloud) StateMgr(name string) (statemgr.Full, error) {
versionOptions := tfe.WorkspaceUpdateOptions{ versionOptions := tfe.WorkspaceUpdateOptions{
TerraformVersion: tfe.String(tfversion.String()), TerraformVersion: tfe.String(tfversion.String()),
} }
_, err := b.client.Workspaces.UpdateByID(context.Background(), workspace.ID, versionOptions) _, err := b.client.Workspaces.UpdateByID(ctx, workspace.ID, versionOptions)
if err == nil { if err == nil {
remoteTFVersion = tfversion.String() remoteTFVersion = tfversion.String()
} else { } else {
@ -727,7 +727,7 @@ func (b *Cloud) StateMgr(name string) (statemgr.Full, error) {
Tags: b.WorkspaceMapping.tfeTags(), Tags: b.WorkspaceMapping.tfeTags(),
} }
log.Printf("[TRACE] cloud: Adding tags for cloud backend workspace %s/%s", b.organization, name) log.Printf("[TRACE] cloud: Adding tags for cloud backend workspace %s/%s", b.organization, name)
err = b.client.Workspaces.AddTags(context.Background(), workspace.ID, options) err = b.client.Workspaces.AddTags(ctx, workspace.ID, options)
if err != nil { if err != nil {
return nil, fmt.Errorf("Error updating workspace %s: %w", name, err) return nil, fmt.Errorf("Error updating workspace %s: %w", name, err)
} }

View File

@ -85,7 +85,9 @@ func TestCloud_applyBasic(t *testing.T) {
op.UIOut = b.CLI op.UIOut = b.CLI
op.Workspace = testBackendSingleWorkspaceName op.Workspace = testBackendSingleWorkspaceName
run, err := b.Operation(context.Background(), op) ctx := context.Background()
run, err := b.Operation(ctx, op)
if err != nil { if err != nil {
t.Fatalf("error starting operation: %v", err) t.Fatalf("error starting operation: %v", err)
} }
@ -113,7 +115,7 @@ func TestCloud_applyBasic(t *testing.T) {
t.Fatalf("expected apply summery in output: %s", output) t.Fatalf("expected apply summery in output: %s", output)
} }
stateMgr, _ := b.StateMgr(testBackendSingleWorkspaceName) stateMgr, _ := b.StateMgr(ctx, testBackendSingleWorkspaceName)
// An error suggests that the state was not unlocked after apply // An error suggests that the state was not unlocked after apply
if _, err := stateMgr.Lock(statemgr.NewLockInfo()); err != nil { if _, err := stateMgr.Lock(statemgr.NewLockInfo()); err != nil {
t.Fatalf("unexpected error locking state after apply: %s", err.Error()) t.Fatalf("unexpected error locking state after apply: %s", err.Error())
@ -145,7 +147,9 @@ func TestCloud_applyJSONBasic(t *testing.T) {
mockSROWorkspace(t, b, op.Workspace) mockSROWorkspace(t, b, op.Workspace)
run, err := b.Operation(context.Background(), op) ctx := context.Background()
run, err := b.Operation(ctx, op)
if err != nil { if err != nil {
t.Fatalf("error starting operation: %v", err) t.Fatalf("error starting operation: %v", err)
} }
@ -172,7 +176,7 @@ func TestCloud_applyJSONBasic(t *testing.T) {
t.Fatalf("expected apply summary in output: %s", gotOut) t.Fatalf("expected apply summary in output: %s", gotOut)
} }
stateMgr, _ := b.StateMgr(testBackendSingleWorkspaceName) stateMgr, _ := b.StateMgr(ctx, testBackendSingleWorkspaceName)
// An error suggests that the state was not unlocked after apply // An error suggests that the state was not unlocked after apply
if _, err := stateMgr.Lock(statemgr.NewLockInfo()); err != nil { if _, err := stateMgr.Lock(statemgr.NewLockInfo()); err != nil {
t.Fatalf("unexpected error locking state after apply: %s", err.Error()) t.Fatalf("unexpected error locking state after apply: %s", err.Error())
@ -204,7 +208,9 @@ func TestCloud_applyJSONWithOutputs(t *testing.T) {
mockSROWorkspace(t, b, op.Workspace) mockSROWorkspace(t, b, op.Workspace)
run, err := b.Operation(context.Background(), op) ctx := context.Background()
run, err := b.Operation(ctx, op)
if err != nil { if err != nil {
t.Fatalf("error starting operation: %v", err) t.Fatalf("error starting operation: %v", err)
} }
@ -260,7 +266,7 @@ func TestCloud_applyJSONWithOutputs(t *testing.T) {
if !strings.Contains(gotOut, expectedComplexOutput) { if !strings.Contains(gotOut, expectedComplexOutput) {
t.Fatalf("expected output: %s, got: %s", expectedComplexOutput, gotOut) t.Fatalf("expected output: %s, got: %s", expectedComplexOutput, gotOut)
} }
stateMgr, _ := b.StateMgr(testBackendSingleWorkspaceName) stateMgr, _ := b.StateMgr(ctx, testBackendSingleWorkspaceName)
// An error suggests that the state was not unlocked after apply // An error suggests that the state was not unlocked after apply
if _, err := stateMgr.Lock(statemgr.NewLockInfo()); err != nil { if _, err := stateMgr.Lock(statemgr.NewLockInfo()); err != nil {
t.Fatalf("unexpected error locking state after apply: %s", err.Error()) t.Fatalf("unexpected error locking state after apply: %s", err.Error())
@ -277,7 +283,9 @@ func TestCloud_applyCanceled(t *testing.T) {
op.Workspace = testBackendSingleWorkspaceName op.Workspace = testBackendSingleWorkspaceName
run, err := b.Operation(context.Background(), op) ctx := context.Background()
run, err := b.Operation(ctx, op)
if err != nil { if err != nil {
t.Fatalf("error starting operation: %v", err) t.Fatalf("error starting operation: %v", err)
} }
@ -290,7 +298,7 @@ func TestCloud_applyCanceled(t *testing.T) {
t.Fatal("expected apply operation to fail") t.Fatal("expected apply operation to fail")
} }
stateMgr, _ := b.StateMgr(testBackendSingleWorkspaceName) stateMgr, _ := b.StateMgr(ctx, testBackendSingleWorkspaceName)
if _, err := stateMgr.Lock(statemgr.NewLockInfo()); err != nil { if _, err := stateMgr.Lock(statemgr.NewLockInfo()); err != nil {
t.Fatalf("unexpected error locking state after cancelling apply: %s", err.Error()) t.Fatalf("unexpected error locking state after cancelling apply: %s", err.Error())
} }
@ -481,8 +489,10 @@ func TestCloud_applyWithCloudPlan(t *testing.T) {
Colorize: mockColorize(), Colorize: mockColorize(),
} }
ctx := context.Background()
// Try apply // Try apply
run, err := b.Operation(context.Background(), op) run, err := b.Operation(ctx, op)
if err != nil { if err != nil {
t.Fatalf("error starting operation: %v", err) t.Fatalf("error starting operation: %v", err)
} }
@ -501,7 +511,7 @@ func TestCloud_applyWithCloudPlan(t *testing.T) {
t.Fatalf("expected apply summary in output: %s", gotOut) t.Fatalf("expected apply summary in output: %s", gotOut)
} }
stateMgr, _ := b.StateMgr(testBackendSingleWorkspaceName) stateMgr, _ := b.StateMgr(ctx, testBackendSingleWorkspaceName)
// An error suggests that the state was not unlocked after apply // An error suggests that the state was not unlocked after apply
if _, err := stateMgr.Lock(statemgr.NewLockInfo()); err != nil { if _, err := stateMgr.Lock(statemgr.NewLockInfo()); err != nil {
t.Fatalf("unexpected error locking state after apply: %s", err.Error()) t.Fatalf("unexpected error locking state after apply: %s", err.Error())
@ -698,7 +708,9 @@ func TestCloud_applyNoConfig(t *testing.T) {
op.Workspace = testBackendSingleWorkspaceName op.Workspace = testBackendSingleWorkspaceName
run, err := b.Operation(context.Background(), op) ctx := context.Background()
run, err := b.Operation(ctx, op)
if err != nil { if err != nil {
t.Fatalf("error starting operation: %v", err) t.Fatalf("error starting operation: %v", err)
} }
@ -717,7 +729,7 @@ func TestCloud_applyNoConfig(t *testing.T) {
t.Fatalf("expected configuration files error, got: %v", errOutput) t.Fatalf("expected configuration files error, got: %v", errOutput)
} }
stateMgr, _ := b.StateMgr(testBackendSingleWorkspaceName) stateMgr, _ := b.StateMgr(ctx, testBackendSingleWorkspaceName)
// An error suggests that the state was not unlocked after apply // An error suggests that the state was not unlocked after apply
if _, err := stateMgr.Lock(statemgr.NewLockInfo()); err != nil { if _, err := stateMgr.Lock(statemgr.NewLockInfo()); err != nil {
t.Fatalf("unexpected error locking state after failed apply: %s", err.Error()) t.Fatalf("unexpected error locking state after failed apply: %s", err.Error())
@ -1361,7 +1373,9 @@ func TestCloud_applyJSONWithProvisioner(t *testing.T) {
mockSROWorkspace(t, b, op.Workspace) mockSROWorkspace(t, b, op.Workspace)
run, err := b.Operation(context.Background(), op) ctx := context.Background()
run, err := b.Operation(ctx, op)
if err != nil { if err != nil {
t.Fatalf("error starting operation: %v", err) t.Fatalf("error starting operation: %v", err)
} }
@ -1393,7 +1407,7 @@ func TestCloud_applyJSONWithProvisioner(t *testing.T) {
t.Fatalf("expected provisioner local-exec output in logs: %s", gotOut) t.Fatalf("expected provisioner local-exec output in logs: %s", gotOut)
} }
stateMgr, _ := b.StateMgr(testBackendSingleWorkspaceName) stateMgr, _ := b.StateMgr(ctx, testBackendSingleWorkspaceName)
// An error suggests that the state was not unlocked after apply // An error suggests that the state was not unlocked after apply
if _, err := stateMgr.Lock(statemgr.NewLockInfo()); err != nil { if _, err := stateMgr.Lock(statemgr.NewLockInfo()); err != nil {
t.Fatalf("unexpected error locking state after apply: %s", err.Error()) t.Fatalf("unexpected error locking state after apply: %s", err.Error())

View File

@ -30,14 +30,15 @@ func (b *Cloud) LocalRun(op *backend.Operation) (*backend.LocalRun, statemgr.Ful
}, },
} }
op.StateLocker = op.StateLocker.WithContext(context.Background()) ctx := context.TODO()
op.StateLocker = op.StateLocker.WithContext(ctx)
// Get the remote workspace name. // Get the remote workspace name.
remoteWorkspaceName := b.getRemoteWorkspaceName(op.Workspace) remoteWorkspaceName := b.getRemoteWorkspaceName(op.Workspace)
// Get the latest state. // Get the latest state.
log.Printf("[TRACE] cloud: requesting state manager for workspace %q", remoteWorkspaceName) log.Printf("[TRACE] cloud: requesting state manager for workspace %q", remoteWorkspaceName)
stateMgr, err := b.StateMgr(op.Workspace) stateMgr, err := b.StateMgr(ctx, op.Workspace)
if err != nil { if err != nil {
diags = diags.Append(fmt.Errorf("error loading state: %w", err)) diags = diags.Append(fmt.Errorf("error loading state: %w", err))
return nil, nil, diags return nil, nil, diags

View File

@ -209,7 +209,10 @@ func TestRemoteContextWithVars(t *testing.T) {
key := "key" key := "key"
v.Key = &key v.Key = &key
} }
b.client.Variables.Create(context.TODO(), workspaceID, *v)
ctx := context.Background()
b.client.Variables.Create(ctx, workspaceID, *v)
_, _, diags := b.LocalRun(op) _, _, diags := b.LocalRun(op)
@ -223,7 +226,7 @@ func TestRemoteContextWithVars(t *testing.T) {
} }
// When Context() returns an error, it should unlock the state, // When Context() returns an error, it should unlock the state,
// so re-locking it is expected to succeed. // so re-locking it is expected to succeed.
stateMgr, _ := b.StateMgr(testBackendSingleWorkspaceName) stateMgr, _ := b.StateMgr(ctx, testBackendSingleWorkspaceName)
if _, err := stateMgr.Lock(statemgr.NewLockInfo()); err != nil { if _, err := stateMgr.Lock(statemgr.NewLockInfo()); err != nil {
t.Fatalf("unexpected error locking state: %s", err.Error()) t.Fatalf("unexpected error locking state: %s", err.Error())
} }
@ -232,7 +235,7 @@ func TestRemoteContextWithVars(t *testing.T) {
t.Fatalf("unexpected error\ngot: %s\nwant: <no error>", diags.Err().Error()) t.Fatalf("unexpected error\ngot: %s\nwant: <no error>", diags.Err().Error())
} }
// When Context() succeeds, this should fail w/ "workspace already locked" // When Context() succeeds, this should fail w/ "workspace already locked"
stateMgr, _ := b.StateMgr(testBackendSingleWorkspaceName) stateMgr, _ := b.StateMgr(ctx, testBackendSingleWorkspaceName)
if _, err := stateMgr.Lock(statemgr.NewLockInfo()); err == nil { if _, err := stateMgr.Lock(statemgr.NewLockInfo()); err == nil {
t.Fatal("unexpected success locking state after Context") t.Fatal("unexpected success locking state after Context")
} }
@ -428,8 +431,10 @@ func TestRemoteVariablesDoNotOverride(t *testing.T) {
Variables: test.localVariables, Variables: test.localVariables,
} }
ctx := context.Background()
for _, v := range test.remoteVariables { for _, v := range test.remoteVariables {
b.client.Variables.Create(context.TODO(), workspaceID, *v) b.client.Variables.Create(ctx, workspaceID, *v)
} }
lr, _, diags := b.LocalRun(op) lr, _, diags := b.LocalRun(op)
@ -438,7 +443,7 @@ func TestRemoteVariablesDoNotOverride(t *testing.T) {
t.Fatalf("unexpected error\ngot: %s\nwant: <no error>", diags.Err().Error()) t.Fatalf("unexpected error\ngot: %s\nwant: <no error>", diags.Err().Error())
} }
// When Context() succeeds, this should fail w/ "workspace already locked" // When Context() succeeds, this should fail w/ "workspace already locked"
stateMgr, _ := b.StateMgr(testBackendSingleWorkspaceName) stateMgr, _ := b.StateMgr(ctx, testBackendSingleWorkspaceName)
if _, err := stateMgr.Lock(statemgr.NewLockInfo()); err == nil { if _, err := stateMgr.Lock(statemgr.NewLockInfo()); err == nil {
t.Fatal("unexpected success locking state after Context") t.Fatal("unexpected success locking state after Context")
} }

View File

@ -76,7 +76,9 @@ func TestCloud_planBasic(t *testing.T) {
op.Workspace = testBackendSingleWorkspaceName op.Workspace = testBackendSingleWorkspaceName
run, err := b.Operation(context.Background(), op) ctx := context.Background()
run, err := b.Operation(ctx, op)
if err != nil { if err != nil {
t.Fatalf("error starting operation: %v", err) t.Fatalf("error starting operation: %v", err)
} }
@ -97,7 +99,7 @@ func TestCloud_planBasic(t *testing.T) {
t.Fatalf("expected plan summary in output: %s", output) t.Fatalf("expected plan summary in output: %s", output)
} }
stateMgr, _ := b.StateMgr(testBackendSingleWorkspaceName) stateMgr, _ := b.StateMgr(ctx, testBackendSingleWorkspaceName)
// An error suggests that the state was not unlocked after the operation finished // 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(statemgr.NewLockInfo()); err != nil {
t.Fatalf("unexpected error locking state after successful plan: %s", err.Error()) t.Fatalf("unexpected error locking state after successful plan: %s", err.Error())
@ -123,7 +125,8 @@ func TestCloud_planJSONBasic(t *testing.T) {
mockSROWorkspace(t, b, op.Workspace) mockSROWorkspace(t, b, op.Workspace)
run, err := b.Operation(context.Background(), op) ctx := context.Background()
run, err := b.Operation(ctx, op)
if err != nil { if err != nil {
t.Fatalf("error starting operation: %v", err) t.Fatalf("error starting operation: %v", err)
} }
@ -143,7 +146,7 @@ func TestCloud_planJSONBasic(t *testing.T) {
t.Fatalf("expected plan summary in output: %s", gotOut) t.Fatalf("expected plan summary in output: %s", gotOut)
} }
stateMgr, _ := b.StateMgr(testBackendSingleWorkspaceName) stateMgr, _ := b.StateMgr(ctx, testBackendSingleWorkspaceName)
// An error suggests that the state was not unlocked after the operation finished // 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(statemgr.NewLockInfo()); err != nil {
t.Fatalf("unexpected error locking state after successful plan: %s", err.Error()) t.Fatalf("unexpected error locking state after successful plan: %s", err.Error())
@ -160,7 +163,8 @@ func TestCloud_planCanceled(t *testing.T) {
op.Workspace = testBackendSingleWorkspaceName op.Workspace = testBackendSingleWorkspaceName
run, err := b.Operation(context.Background(), op) ctx := context.Background()
run, err := b.Operation(ctx, op)
if err != nil { if err != nil {
t.Fatalf("error starting operation: %v", err) t.Fatalf("error starting operation: %v", err)
} }
@ -173,7 +177,7 @@ func TestCloud_planCanceled(t *testing.T) {
t.Fatal("expected plan operation to fail") t.Fatal("expected plan operation to fail")
} }
stateMgr, _ := b.StateMgr(testBackendSingleWorkspaceName) stateMgr, _ := b.StateMgr(ctx, testBackendSingleWorkspaceName)
// An error suggests that the state was not unlocked after the operation finished // 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(statemgr.NewLockInfo()); err != nil {
t.Fatalf("unexpected error locking state after cancelled plan: %s", err.Error()) t.Fatalf("unexpected error locking state after cancelled plan: %s", err.Error())
@ -231,7 +235,8 @@ func TestCloud_planJSONFull(t *testing.T) {
mockSROWorkspace(t, b, op.Workspace) mockSROWorkspace(t, b, op.Workspace)
run, err := b.Operation(context.Background(), op) ctx := context.Background()
run, err := b.Operation(ctx, op)
if err != nil { if err != nil {
t.Fatalf("error starting operation: %v", err) t.Fatalf("error starting operation: %v", err)
} }
@ -255,7 +260,7 @@ func TestCloud_planJSONFull(t *testing.T) {
t.Fatalf("expected plan summary in output: %s", gotOut) t.Fatalf("expected plan summary in output: %s", gotOut)
} }
stateMgr, _ := b.StateMgr(testBackendSingleWorkspaceName) stateMgr, _ := b.StateMgr(ctx, testBackendSingleWorkspaceName)
// An error suggests that the state was not unlocked after the operation finished // 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(statemgr.NewLockInfo()); err != nil {
t.Fatalf("unexpected error locking state after successful plan: %s", err.Error()) t.Fatalf("unexpected error locking state after successful plan: %s", err.Error())
@ -1310,7 +1315,8 @@ func TestCloud_planImportConfigGeneration(t *testing.T) {
mockSROWorkspace(t, b, op.Workspace) mockSROWorkspace(t, b, op.Workspace)
run, err := b.Operation(context.Background(), op) ctx := context.Background()
run, err := b.Operation(ctx, op)
if err != nil { if err != nil {
t.Fatalf("error starting operation: %v", err) t.Fatalf("error starting operation: %v", err)
} }
@ -1329,7 +1335,7 @@ func TestCloud_planImportConfigGeneration(t *testing.T) {
t.Fatalf("expected plan summary in output: %s", gotOut) t.Fatalf("expected plan summary in output: %s", gotOut)
} }
stateMgr, _ := b.StateMgr(testBackendSingleWorkspaceName) stateMgr, _ := b.StateMgr(ctx, testBackendSingleWorkspaceName)
// An error suggests that the state was not unlocked after the operation finished // 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(statemgr.NewLockInfo()); err != nil {
t.Fatalf("unexpected error locking state after successful plan: %s", err.Error()) t.Fatalf("unexpected error locking state after successful plan: %s", err.Error())

View File

@ -60,7 +60,8 @@ func TestCloud_refreshBasicActuallyRunsApplyRefresh(t *testing.T) {
op.PlanMode = plans.RefreshOnlyMode op.PlanMode = plans.RefreshOnlyMode
op.Workspace = testBackendSingleWorkspaceName op.Workspace = testBackendSingleWorkspaceName
run, err := b.Operation(context.Background(), op) ctx := context.Background()
run, err := b.Operation(ctx, op)
if err != nil { if err != nil {
t.Fatalf("error starting operation: %v", err) t.Fatalf("error starting operation: %v", err)
} }
@ -75,7 +76,7 @@ func TestCloud_refreshBasicActuallyRunsApplyRefresh(t *testing.T) {
t.Fatalf("expected TFC header in output: %s", output) t.Fatalf("expected TFC header in output: %s", output)
} }
stateMgr, _ := b.StateMgr(testBackendSingleWorkspaceName) stateMgr, _ := b.StateMgr(ctx, testBackendSingleWorkspaceName)
// An error suggests that the state was not unlocked after apply // An error suggests that the state was not unlocked after apply
if _, err := stateMgr.Lock(statemgr.NewLockInfo()); err != nil { if _, err := stateMgr.Lock(statemgr.NewLockInfo()); err != nil {
t.Fatalf("unexpected error locking state after apply: %s", err.Error()) t.Fatalf("unexpected error locking state after apply: %s", err.Error())

View File

@ -30,6 +30,8 @@ func TestCloud_backendWithName(t *testing.T) {
b, bCleanup := testBackendWithName(t) b, bCleanup := testBackendWithName(t)
defer bCleanup() defer bCleanup()
ctx := context.Background()
workspaces, err := b.Workspaces() workspaces, err := b.Workspaces()
if err != nil { if err != nil {
t.Fatalf("error: %v", err) t.Fatalf("error: %v", err)
@ -39,7 +41,7 @@ func TestCloud_backendWithName(t *testing.T) {
t.Fatalf("should only have a single configured workspace matching the configured 'name' strategy, but got: %#v", workspaces) t.Fatalf("should only have a single configured workspace matching the configured 'name' strategy, but got: %#v", workspaces)
} }
if _, err := b.StateMgr("foo"); err != backend.ErrWorkspacesNotSupported { if _, err := b.StateMgr(ctx, "foo"); err != backend.ErrWorkspacesNotSupported {
t.Fatalf("expected fetching a state which is NOT the single configured workspace to have an ErrWorkspacesNotSupported error, but got: %v", err) t.Fatalf("expected fetching a state which is NOT the single configured workspace to have an ErrWorkspacesNotSupported error, but got: %v", err)
} }
@ -93,9 +95,11 @@ func TestCloud_backendWithTags(t *testing.T) {
backend.TestBackendStates(t, b) backend.TestBackendStates(t, b)
ctx := context.Background()
// Test pagination works // Test pagination works
for i := 0; i < 25; i++ { for i := 0; i < 25; i++ {
_, err := b.StateMgr(fmt.Sprintf("foo-%d", i+1)) _, err := b.StateMgr(ctx, fmt.Sprintf("foo-%d", i+1))
if err != nil { if err != nil {
t.Fatalf("error: %s", err) t.Fatalf("error: %s", err)
} }
@ -844,16 +848,18 @@ func TestCloud_setUnavailableTerraformVersion(t *testing.T) {
b, _, bCleanup := testBackend(t, config, nil) b, _, bCleanup := testBackend(t, config, nil)
defer bCleanup() defer bCleanup()
ctx := context.Background()
// Make sure the workspace doesn't exist yet -- otherwise, we can't test what // Make sure the workspace doesn't exist yet -- otherwise, we can't test what
// happens when a workspace gets created. This is why we can't use "name" in // happens when a workspace gets created. This is why we can't use "name" in
// the backend config above, btw: if you do, testBackend() creates the default // the backend config above, btw: if you do, testBackend() creates the default
// workspace before we get a chance to do anything. // workspace before we get a chance to do anything.
_, err := b.client.Workspaces.Read(context.Background(), b.organization, workspaceName) _, err := b.client.Workspaces.Read(ctx, b.organization, workspaceName)
if err != tfe.ErrResourceNotFound { if err != tfe.ErrResourceNotFound {
t.Fatalf("the workspace we were about to try and create (%s/%s) already exists in the mocks somehow, so this test isn't trustworthy anymore", b.organization, workspaceName) t.Fatalf("the workspace we were about to try and create (%s/%s) already exists in the mocks somehow, so this test isn't trustworthy anymore", b.organization, workspaceName)
} }
_, err = b.StateMgr(workspaceName) _, err = b.StateMgr(ctx, workspaceName)
if err != nil { if err != nil {
t.Fatalf("expected no error from StateMgr, despite not being able to set remote TF version: %#v", err) t.Fatalf("expected no error from StateMgr, despite not being able to set remote TF version: %#v", err)
} }
@ -1059,7 +1065,9 @@ func TestCloud_addAndRemoveWorkspacesDefault(t *testing.T) {
b, bCleanup := testBackendWithName(t) b, bCleanup := testBackendWithName(t)
defer bCleanup() defer bCleanup()
if _, err := b.StateMgr(testBackendSingleWorkspaceName); err != nil { ctx := context.Background()
if _, err := b.StateMgr(ctx, testBackendSingleWorkspaceName); err != nil {
t.Fatalf("expected no error, got %v", err) t.Fatalf("expected no error, got %v", err)
} }
@ -1092,10 +1100,12 @@ func TestCloud_StateMgr_versionCheck(t *testing.T) {
tfversion.Version = v0140.String() tfversion.Version = v0140.String()
tfversion.SemVer = v0140 tfversion.SemVer = v0140
ctx := context.Background()
// Update the mock remote workspace Terraform version to match the local // Update the mock remote workspace Terraform version to match the local
// Terraform version // Terraform version
if _, err := b.client.Workspaces.Update( if _, err := b.client.Workspaces.Update(
context.Background(), ctx,
b.organization, b.organization,
b.WorkspaceMapping.Name, b.WorkspaceMapping.Name,
tfe.WorkspaceUpdateOptions{ tfe.WorkspaceUpdateOptions{
@ -1106,7 +1116,7 @@ func TestCloud_StateMgr_versionCheck(t *testing.T) {
} }
// This should succeed // This should succeed
if _, err := b.StateMgr(testBackendSingleWorkspaceName); err != nil { if _, err := b.StateMgr(ctx, testBackendSingleWorkspaceName); err != nil {
t.Fatalf("expected no error, got %v", err) t.Fatalf("expected no error, got %v", err)
} }
@ -1124,7 +1134,7 @@ func TestCloud_StateMgr_versionCheck(t *testing.T) {
// This should fail // This should fail
want := `Remote workspace TF version "0.13.5" does not match local OpenTofu version "0.14.0"` want := `Remote workspace TF version "0.13.5" does not match local OpenTofu version "0.14.0"`
if _, err := b.StateMgr(testBackendSingleWorkspaceName); err.Error() != want { if _, err := b.StateMgr(ctx, testBackendSingleWorkspaceName); err.Error() != want {
t.Fatalf("wrong error\n got: %v\nwant: %v", err.Error(), want) t.Fatalf("wrong error\n got: %v\nwant: %v", err.Error(), want)
} }
} }
@ -1150,9 +1160,11 @@ func TestCloud_StateMgr_versionCheckLatest(t *testing.T) {
tfversion.Version = v0140.String() tfversion.Version = v0140.String()
tfversion.SemVer = v0140 tfversion.SemVer = v0140
ctx := context.Background()
// Update the remote workspace to the pseudo-version "latest" // Update the remote workspace to the pseudo-version "latest"
if _, err := b.client.Workspaces.Update( if _, err := b.client.Workspaces.Update(
context.Background(), ctx,
b.organization, b.organization,
b.WorkspaceMapping.Name, b.WorkspaceMapping.Name,
tfe.WorkspaceUpdateOptions{ tfe.WorkspaceUpdateOptions{
@ -1163,7 +1175,7 @@ func TestCloud_StateMgr_versionCheckLatest(t *testing.T) {
} }
// This should succeed despite not being a string match // This should succeed despite not being a string match
if _, err := b.StateMgr(testBackendSingleWorkspaceName); err != nil { if _, err := b.StateMgr(ctx, testBackendSingleWorkspaceName); err != nil {
t.Fatalf("expected no error, got %v", err) t.Fatalf("expected no error, got %v", err)
} }
} }
@ -1353,12 +1365,14 @@ func TestCloudBackend_DeleteWorkspace_SafeAndForce(t *testing.T) {
safeDeleteWorkspaceName := "safe-delete-workspace" safeDeleteWorkspaceName := "safe-delete-workspace"
forceDeleteWorkspaceName := "force-delete-workspace" forceDeleteWorkspaceName := "force-delete-workspace"
_, err := b.StateMgr(safeDeleteWorkspaceName) ctx := context.Background()
_, err := b.StateMgr(ctx, safeDeleteWorkspaceName)
if err != nil { if err != nil {
t.Fatalf("error: %s", err) t.Fatalf("error: %s", err)
} }
_, err = b.StateMgr(forceDeleteWorkspaceName) _, err = b.StateMgr(ctx, forceDeleteWorkspaceName)
if err != nil { if err != nil {
t.Fatalf("error: %s", err) t.Fatalf("error: %s", err)
} }
@ -1369,17 +1383,16 @@ func TestCloudBackend_DeleteWorkspace_SafeAndForce(t *testing.T) {
t.Fatalf("error fetching workspace names: %v", err) t.Fatalf("error fetching workspace names: %v", err)
} }
if len(wl) != 2 { if len(wl) != 2 {
t.Fatalf("expected 2 workspaced but got %d", len(wl)) t.Fatalf("expected 2 workspaces but got %d", len(wl))
} }
c := context.Background() safeDeleteWorkspace, err := b.client.Workspaces.Read(ctx, b.organization, safeDeleteWorkspaceName)
safeDeleteWorkspace, err := b.client.Workspaces.Read(c, b.organization, safeDeleteWorkspaceName)
if err != nil { if err != nil {
t.Fatalf("error fetching workspace: %v", err) t.Fatalf("error fetching workspace: %v", err)
} }
// Lock a workspace so that it should fail to be safe deleted // Lock a workspace so that it should fail to be safe deleted
_, err = b.client.Workspaces.Lock(context.Background(), safeDeleteWorkspace.ID, tfe.WorkspaceLockOptions{Reason: tfe.String("test")}) _, err = b.client.Workspaces.Lock(ctx, safeDeleteWorkspace.ID, tfe.WorkspaceLockOptions{Reason: tfe.String("test")})
if err != nil { if err != nil {
t.Fatalf("error locking workspace: %v", err) t.Fatalf("error locking workspace: %v", err)
} }
@ -1389,7 +1402,7 @@ func TestCloudBackend_DeleteWorkspace_SafeAndForce(t *testing.T) {
} }
// unlock the workspace and confirm that safe-delete now works // unlock the workspace and confirm that safe-delete now works
_, err = b.client.Workspaces.Unlock(context.Background(), safeDeleteWorkspace.ID) _, err = b.client.Workspaces.Unlock(ctx, safeDeleteWorkspace.ID)
if err != nil { if err != nil {
t.Fatalf("error unlocking workspace: %v", err) t.Fatalf("error unlocking workspace: %v", err)
} }
@ -1399,11 +1412,11 @@ func TestCloudBackend_DeleteWorkspace_SafeAndForce(t *testing.T) {
} }
// lock a workspace and then confirm that force deleting it works // lock a workspace and then confirm that force deleting it works
forceDeleteWorkspace, err := b.client.Workspaces.Read(c, b.organization, forceDeleteWorkspaceName) forceDeleteWorkspace, err := b.client.Workspaces.Read(ctx, b.organization, forceDeleteWorkspaceName)
if err != nil { if err != nil {
t.Fatalf("error fetching workspace: %v", err) t.Fatalf("error fetching workspace: %v", err)
} }
_, err = b.client.Workspaces.Lock(context.Background(), forceDeleteWorkspace.ID, tfe.WorkspaceLockOptions{Reason: tfe.String("test")}) _, err = b.client.Workspaces.Lock(ctx, forceDeleteWorkspace.ID, tfe.WorkspaceLockOptions{Reason: tfe.String("test")})
if err != nil { if err != nil {
t.Fatalf("error locking workspace: %v", err) t.Fatalf("error locking workspace: %v", err)
} }

View File

@ -144,11 +144,13 @@ func TestCloudLocks(t *testing.T) {
back, bCleanup := testBackendWithName(t) back, bCleanup := testBackendWithName(t)
defer bCleanup() defer bCleanup()
a, err := back.StateMgr(testBackendSingleWorkspaceName) ctx := context.Background()
a, err := back.StateMgr(ctx, testBackendSingleWorkspaceName)
if err != nil { if err != nil {
t.Fatalf("expected no error, got %v", err) t.Fatalf("expected no error, got %v", err)
} }
b, err := back.StateMgr(testBackendSingleWorkspaceName) b, err := back.StateMgr(ctx, testBackendSingleWorkspaceName)
if err != nil { if err != nil {
t.Fatalf("expected no error, got %v", err) t.Fatalf("expected no error, got %v", err)
} }

View File

@ -154,7 +154,9 @@ func testCloudState(t *testing.T) *State {
b, bCleanup := testBackendWithName(t) b, bCleanup := testBackendWithName(t)
defer bCleanup() defer bCleanup()
raw, err := b.StateMgr(testBackendSingleWorkspaceName) ctx := context.Background()
raw, err := b.StateMgr(ctx, testBackendSingleWorkspaceName)
if err != nil { if err != nil {
t.Fatalf("error: %v", err) t.Fatalf("error: %v", err)
} }

View File

@ -219,7 +219,7 @@ func (c *InitCommand) Run(args []string) int {
c.Ui.Error(fmt.Sprintf("Error selecting workspace: %s", err)) c.Ui.Error(fmt.Sprintf("Error selecting workspace: %s", err))
return 1 return 1
} }
sMgr, err := back.StateMgr(workspace) sMgr, err := back.StateMgr(ctx, workspace)
if err != nil { if err != nil {
c.Ui.Error(fmt.Sprintf("Error loading state: %s", err)) c.Ui.Error(fmt.Sprintf("Error loading state: %s", err))
return 1 return 1

View File

@ -975,9 +975,11 @@ func (m *Meta) backend_C_r_s(c *configs.Backend, cHash int, sMgr *clistate.Local
return nil, diags return nil, diags
} }
ctx := context.TODO()
var localStates []statemgr.Full var localStates []statemgr.Full
for _, workspace := range workspaces { for _, workspace := range workspaces {
localState, err := localB.StateMgr(workspace) localState, err := localB.StateMgr(ctx, workspace)
if err != nil { if err != nil {
diags = diags.Append(fmt.Errorf(errBackendLocalRead, err)) diags = diags.Append(fmt.Errorf(errBackendLocalRead, err))
return nil, diags return nil, diags
@ -1063,8 +1065,6 @@ func (m *Meta) backend_C_r_s(c *configs.Backend, cHash int, sMgr *clistate.Local
defer stateLocker.Unlock() defer stateLocker.Unlock()
} }
ctx := context.TODO()
configJSON, err := ctyjson.Marshal(configVal, b.ConfigSchema(ctx).ImpliedType()) configJSON, err := ctyjson.Marshal(configVal, b.ConfigSchema(ctx).ImpliedType())
if err != nil { if err != nil {
diags = diags.Append(fmt.Errorf("Can't serialize backend configuration as JSON: %w", err)) diags = diags.Append(fmt.Errorf("Can't serialize backend configuration as JSON: %w", err))

View File

@ -250,7 +250,7 @@ func (m *Meta) backendMigrateState_S_s(opts *backendMigrateOpts) error {
// Copy the default state // Copy the default state
opts.sourceWorkspace = currentWorkspace opts.sourceWorkspace = currentWorkspace
// now switch back to the default env so we can acccess the new backend // now switch back to the default env so we can access the new backend
m.SetWorkspace(backend.DefaultStateName) m.SetWorkspace(backend.DefaultStateName)
return m.backendMigrateState_s_s(opts) return m.backendMigrateState_s_s(opts)
@ -260,7 +260,9 @@ func (m *Meta) backendMigrateState_S_s(opts *backendMigrateOpts) error {
func (m *Meta) backendMigrateState_s_s(opts *backendMigrateOpts) error { func (m *Meta) backendMigrateState_s_s(opts *backendMigrateOpts) error {
log.Printf("[INFO] backendMigrateState: single-to-single migrating %q workspace to %q workspace", opts.sourceWorkspace, opts.destinationWorkspace) log.Printf("[INFO] backendMigrateState: single-to-single migrating %q workspace to %q workspace", opts.sourceWorkspace, opts.destinationWorkspace)
sourceState, err := opts.Source.StateMgr(opts.sourceWorkspace) ctx := context.TODO()
sourceState, err := opts.Source.StateMgr(ctx, opts.sourceWorkspace)
if err != nil { if err != nil {
return fmt.Errorf(strings.TrimSpace( return fmt.Errorf(strings.TrimSpace(
errMigrateSingleLoadDefault), opts.SourceType, err) errMigrateSingleLoadDefault), opts.SourceType, err)
@ -276,7 +278,7 @@ func (m *Meta) backendMigrateState_s_s(opts *backendMigrateOpts) error {
return nil return nil
} }
destinationState, err := opts.Destination.StateMgr(opts.destinationWorkspace) destinationState, err := opts.Destination.StateMgr(ctx, opts.destinationWorkspace)
if err == backend.ErrDefaultWorkspaceNotSupported { if err == backend.ErrDefaultWorkspaceNotSupported {
// If the backend doesn't support using the default state, we ask the user // If the backend doesn't support using the default state, we ask the user
// for a new name and migrate the default state to the given named state. // for a new name and migrate the default state to the given named state.
@ -290,7 +292,7 @@ func (m *Meta) backendMigrateState_s_s(opts *backendMigrateOpts) error {
// Update the name of the destination state. // Update the name of the destination state.
opts.destinationWorkspace = name opts.destinationWorkspace = name
destinationState, err := opts.Destination.StateMgr(opts.destinationWorkspace) destinationState, err := opts.Destination.StateMgr(ctx, opts.destinationWorkspace)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -557,7 +559,7 @@ func (m *Meta) backendMigrateTFC(opts *backendMigrateOpts) error {
if err != nil { if err != nil {
return err return err
} }
//to be used below, not yet implamented //to be used below, not yet implemented
// destinationWorkspaces, destinationSingleState // destinationWorkspaces, destinationSingleState
_, _, err = retrieveWorkspaces(opts.Destination, opts.SourceType) _, _, err = retrieveWorkspaces(opts.Destination, opts.SourceType)
if err != nil { if err != nil {
@ -592,9 +594,11 @@ func (m *Meta) backendMigrateTFC(opts *backendMigrateOpts) error {
log.Printf("[INFO] backendMigrateTFC: single-to-single migration from source %s to destination %q", opts.sourceWorkspace, opts.destinationWorkspace) log.Printf("[INFO] backendMigrateTFC: single-to-single migration from source %s to destination %q", opts.sourceWorkspace, opts.destinationWorkspace)
ctx := context.TODO()
// If the current workspace is has no state we do not need to ask // If the current workspace is has no state we do not need to ask
// if they want to migrate the state. // if they want to migrate the state.
sourceState, err := opts.Source.StateMgr(currentWorkspace) sourceState, err := opts.Source.StateMgr(ctx, currentWorkspace)
if err != nil { if err != nil {
return err return err
} }
@ -662,6 +666,8 @@ func (m *Meta) backendMigrateTFC(opts *backendMigrateOpts) error {
func (m *Meta) backendMigrateState_S_TFC(opts *backendMigrateOpts, sourceWorkspaces []string) error { func (m *Meta) backendMigrateState_S_TFC(opts *backendMigrateOpts, sourceWorkspaces []string) error {
log.Print("[TRACE] backendMigrateState: migrating all named workspaces") log.Print("[TRACE] backendMigrateState: migrating all named workspaces")
ctx := context.TODO()
currentWorkspace, err := m.Workspace() currentWorkspace, err := m.Workspace()
if err != nil { if err != nil {
return err return err
@ -680,7 +686,7 @@ func (m *Meta) backendMigrateState_S_TFC(opts *backendMigrateOpts, sourceWorkspa
if sourceWorkspaces[i] == backend.DefaultStateName { if sourceWorkspaces[i] == backend.DefaultStateName {
// For the default workspace we want to look to see if there is any state // For the default workspace we want to look to see if there is any state
// before we ask for a workspace name to migrate the default workspace into. // before we ask for a workspace name to migrate the default workspace into.
sourceState, err := opts.Source.StateMgr(backend.DefaultStateName) sourceState, err := opts.Source.StateMgr(ctx, backend.DefaultStateName)
if err != nil { if err != nil {
return fmt.Errorf(strings.TrimSpace( return fmt.Errorf(strings.TrimSpace(
errMigrateSingleLoadDefault), opts.SourceType, err) errMigrateSingleLoadDefault), opts.SourceType, err)

View File

@ -43,8 +43,10 @@ func TestMetaBackend_emptyDir(t *testing.T) {
t.Fatal(diags.Err()) t.Fatal(diags.Err())
} }
ctx := context.Background()
// Write some state // Write some state
s, err := b.StateMgr(backend.DefaultStateName) s, err := b.StateMgr(ctx, backend.DefaultStateName)
if err != nil { if err != nil {
t.Fatalf("unexpected error: %s", err) t.Fatalf("unexpected error: %s", err)
} }
@ -112,8 +114,10 @@ func TestMetaBackend_emptyWithDefaultState(t *testing.T) {
t.Fatal(diags.Err()) t.Fatal(diags.Err())
} }
ctx := context.Background()
// Check the state // Check the state
s, err := b.StateMgr(backend.DefaultStateName) s, err := b.StateMgr(ctx, backend.DefaultStateName)
if err != nil { if err != nil {
t.Fatalf("unexpected error: %s", err) t.Fatalf("unexpected error: %s", err)
} }
@ -183,8 +187,10 @@ func TestMetaBackend_emptyWithExplicitState(t *testing.T) {
t.Fatal(diags.Err()) t.Fatal(diags.Err())
} }
ctx := context.Background()
// Check the state // Check the state
s, err := b.StateMgr(backend.DefaultStateName) s, err := b.StateMgr(ctx, backend.DefaultStateName)
if err != nil { if err != nil {
t.Fatalf("unexpected error: %s", err) t.Fatalf("unexpected error: %s", err)
} }
@ -251,8 +257,10 @@ func TestMetaBackend_configureNew(t *testing.T) {
t.Fatal(diags.Err()) t.Fatal(diags.Err())
} }
ctx := context.Background()
// Check the state // Check the state
s, err := b.StateMgr(backend.DefaultStateName) s, err := b.StateMgr(ctx, backend.DefaultStateName)
if err != nil { if err != nil {
t.Fatalf("unexpected error: %s", err) t.Fatalf("unexpected error: %s", err)
} }
@ -322,8 +330,10 @@ func TestMetaBackend_configureNewWithState(t *testing.T) {
t.Fatal(diags.Err()) t.Fatal(diags.Err())
} }
ctx := context.Background()
// Check the state // Check the state
s, err := b.StateMgr(backend.DefaultStateName) s, err := b.StateMgr(ctx, backend.DefaultStateName)
if err != nil { if err != nil {
t.Fatalf("unexpected error: %s", err) t.Fatalf("unexpected error: %s", err)
} }
@ -445,8 +455,10 @@ func TestMetaBackend_configureNewWithStateNoMigrate(t *testing.T) {
t.Fatal(diags.Err()) t.Fatal(diags.Err())
} }
ctx := context.Background()
// Check the state // Check the state
s, err := b.StateMgr(backend.DefaultStateName) s, err := b.StateMgr(ctx, backend.DefaultStateName)
if err != nil { if err != nil {
t.Fatalf("unexpected error: %s", err) t.Fatalf("unexpected error: %s", err)
} }
@ -488,8 +500,10 @@ func TestMetaBackend_configureNewWithStateExisting(t *testing.T) {
t.Fatal(diags.Err()) t.Fatal(diags.Err())
} }
ctx := context.Background()
// Check the state // Check the state
s, err := b.StateMgr(backend.DefaultStateName) s, err := b.StateMgr(ctx, backend.DefaultStateName)
if err != nil { if err != nil {
t.Fatalf("unexpected error: %s", err) t.Fatalf("unexpected error: %s", err)
} }
@ -560,8 +574,10 @@ func TestMetaBackend_configureNewWithStateExistingNoMigrate(t *testing.T) {
t.Fatal(diags.Err()) t.Fatal(diags.Err())
} }
ctx := context.Background()
// Check the state // Check the state
s, err := b.StateMgr(backend.DefaultStateName) s, err := b.StateMgr(ctx, backend.DefaultStateName)
if err != nil { if err != nil {
t.Fatalf("unexpected error: %s", err) t.Fatalf("unexpected error: %s", err)
} }
@ -625,8 +641,10 @@ func TestMetaBackend_configuredUnchanged(t *testing.T) {
t.Fatal(diags.Err()) t.Fatal(diags.Err())
} }
ctx := context.Background()
// Check the state // Check the state
s, err := b.StateMgr(backend.DefaultStateName) s, err := b.StateMgr(ctx, backend.DefaultStateName)
if err != nil { if err != nil {
t.Fatalf("unexpected error: %s", err) t.Fatalf("unexpected error: %s", err)
} }
@ -671,8 +689,10 @@ func TestMetaBackend_configuredChange(t *testing.T) {
t.Fatal(diags.Err()) t.Fatal(diags.Err())
} }
ctx := context.Background()
// Check the state // Check the state
s, err := b.StateMgr(backend.DefaultStateName) s, err := b.StateMgr(ctx, backend.DefaultStateName)
if err != nil { if err != nil {
t.Fatalf("unexpected error: %s", err) t.Fatalf("unexpected error: %s", err)
} }
@ -757,8 +777,10 @@ func TestMetaBackend_reconfigureChange(t *testing.T) {
t.Fatal(diags.Err()) t.Fatal(diags.Err())
} }
ctx := context.Background()
// Check the state // Check the state
s, err := b.StateMgr(backend.DefaultStateName) s, err := b.StateMgr(ctx, backend.DefaultStateName)
if err != nil { if err != nil {
t.Fatalf("unexpected error: %s", err) t.Fatalf("unexpected error: %s", err)
} }
@ -897,8 +919,10 @@ func TestMetaBackend_configuredChangeCopy(t *testing.T) {
t.Fatal(diags.Err()) t.Fatal(diags.Err())
} }
ctx := context.Background()
// Check the state // Check the state
s, err := b.StateMgr(backend.DefaultStateName) s, err := b.StateMgr(ctx, backend.DefaultStateName)
if err != nil { if err != nil {
t.Fatalf("unexpected error: %s", err) t.Fatalf("unexpected error: %s", err)
} }
@ -950,8 +974,10 @@ func TestMetaBackend_configuredChangeCopy_singleState(t *testing.T) {
t.Fatal(diags.Err()) t.Fatal(diags.Err())
} }
ctx := context.Background()
// Check the state // Check the state
s, err := b.StateMgr(backend.DefaultStateName) s, err := b.StateMgr(ctx, backend.DefaultStateName)
if err != nil { if err != nil {
t.Fatalf("unexpected error: %s", err) t.Fatalf("unexpected error: %s", err)
} }
@ -1004,8 +1030,10 @@ func TestMetaBackend_configuredChangeCopy_multiToSingleDefault(t *testing.T) {
t.Fatal(diags.Err()) t.Fatal(diags.Err())
} }
ctx := context.Background()
// Check the state // Check the state
s, err := b.StateMgr(backend.DefaultStateName) s, err := b.StateMgr(ctx, backend.DefaultStateName)
if err != nil { if err != nil {
t.Fatalf("unexpected error: %s", err) t.Fatalf("unexpected error: %s", err)
} }
@ -1058,8 +1086,10 @@ func TestMetaBackend_configuredChangeCopy_multiToSingle(t *testing.T) {
t.Fatal(diags.Err()) t.Fatal(diags.Err())
} }
ctx := context.Background()
// Check the state // Check the state
s, err := b.StateMgr(backend.DefaultStateName) s, err := b.StateMgr(ctx, backend.DefaultStateName)
if err != nil { if err != nil {
t.Fatalf("unexpected error: %s", err) t.Fatalf("unexpected error: %s", err)
} }
@ -1132,8 +1162,10 @@ func TestMetaBackend_configuredChangeCopy_multiToSingleCurrentEnv(t *testing.T)
t.Fatal(diags.Err()) t.Fatal(diags.Err())
} }
ctx := context.Background()
// Check the state // Check the state
s, err := b.StateMgr(backend.DefaultStateName) s, err := b.StateMgr(ctx, backend.DefaultStateName)
if err != nil { if err != nil {
t.Fatalf("unexpected error: %s", err) t.Fatalf("unexpected error: %s", err)
} }
@ -1199,9 +1231,11 @@ func TestMetaBackend_configuredChangeCopy_multiToMulti(t *testing.T) {
t.Fatalf("bad: %#v", workspaces) t.Fatalf("bad: %#v", workspaces)
} }
ctx := context.Background()
{ {
// Check the default state // Check the default state
s, err := b.StateMgr(backend.DefaultStateName) s, err := b.StateMgr(ctx, backend.DefaultStateName)
if err != nil { if err != nil {
t.Fatalf("unexpected error: %s", err) t.Fatalf("unexpected error: %s", err)
} }
@ -1219,7 +1253,7 @@ func TestMetaBackend_configuredChangeCopy_multiToMulti(t *testing.T) {
{ {
// Check the other state // Check the other state
s, err := b.StateMgr("env2") s, err := b.StateMgr(ctx, "env2")
if err != nil { if err != nil {
t.Fatalf("unexpected error: %s", err) t.Fatalf("unexpected error: %s", err)
} }
@ -1297,9 +1331,11 @@ func TestMetaBackend_configuredChangeCopy_multiToNoDefaultWithDefault(t *testing
t.Fatalf("bad: %#v", workspaces) t.Fatalf("bad: %#v", workspaces)
} }
ctx := context.Background()
{ {
// Check the renamed default state // Check the renamed default state
s, err := b.StateMgr("env1") s, err := b.StateMgr(ctx, "env1")
if err != nil { if err != nil {
t.Fatalf("unexpected error: %s", err) t.Fatalf("unexpected error: %s", err)
} }
@ -1372,8 +1408,9 @@ func TestMetaBackend_configuredChangeCopy_multiToNoDefaultWithoutDefault(t *test
} }
{ {
ctx := context.Background()
// Check the named state // Check the named state
s, err := b.StateMgr("env2") s, err := b.StateMgr(ctx, "env2")
if err != nil { if err != nil {
t.Fatalf("unexpected error: %s", err) t.Fatalf("unexpected error: %s", err)
} }
@ -1425,8 +1462,10 @@ func TestMetaBackend_configuredUnset(t *testing.T) {
t.Fatal(diags.Err()) t.Fatal(diags.Err())
} }
ctx := context.Background()
// Check the state // Check the state
s, err := b.StateMgr(backend.DefaultStateName) s, err := b.StateMgr(ctx, backend.DefaultStateName)
if err != nil { if err != nil {
t.Fatalf("unexpected error: %s", err) t.Fatalf("unexpected error: %s", err)
} }
@ -1487,8 +1526,10 @@ func TestMetaBackend_configuredUnsetCopy(t *testing.T) {
t.Fatal(diags.Err()) t.Fatal(diags.Err())
} }
ctx := context.Background()
// Check the state // Check the state
s, err := b.StateMgr(backend.DefaultStateName) s, err := b.StateMgr(ctx, backend.DefaultStateName)
if err != nil { if err != nil {
t.Fatalf("unexpected error: %s", err) t.Fatalf("unexpected error: %s", err)
} }
@ -1555,8 +1596,10 @@ func TestMetaBackend_planLocal(t *testing.T) {
t.Fatal(diags.Err()) t.Fatal(diags.Err())
} }
ctx := context.Background()
// Check the state // Check the state
s, err := b.StateMgr(backend.DefaultStateName) s, err := b.StateMgr(ctx, backend.DefaultStateName)
if err != nil { if err != nil {
t.Fatalf("unexpected error: %s", err) t.Fatalf("unexpected error: %s", err)
} }
@ -1656,8 +1699,10 @@ func TestMetaBackend_planLocalStatePath(t *testing.T) {
t.Fatal(diags.Err()) t.Fatal(diags.Err())
} }
ctx := context.Background()
// Check the state // Check the state
s, err := b.StateMgr(backend.DefaultStateName) s, err := b.StateMgr(ctx, backend.DefaultStateName)
if err != nil { if err != nil {
t.Fatalf("unexpected error: %s", err) t.Fatalf("unexpected error: %s", err)
} }
@ -1745,8 +1790,10 @@ func TestMetaBackend_planLocalMatch(t *testing.T) {
t.Fatal(diags.Err()) t.Fatal(diags.Err())
} }
ctx := context.Background()
// Check the state // Check the state
s, err := b.StateMgr(backend.DefaultStateName) s, err := b.StateMgr(ctx, backend.DefaultStateName)
if err != nil { if err != nil {
t.Fatalf("unexpected error: %s", err) t.Fatalf("unexpected error: %s", err)
} }

View File

@ -4,6 +4,7 @@
package command package command
import ( import (
"context"
"fmt" "fmt"
"strings" "strings"
@ -78,8 +79,10 @@ func (c *OutputCommand) Outputs(statePath string) (map[string]*states.OutputValu
return nil, diags return nil, diags
} }
ctx := context.TODO()
// Get the state // Get the state
stateStore, err := b.StateMgr(env) stateStore, err := b.StateMgr(ctx, env)
if err != nil { if err != nil {
diags = diags.Append(fmt.Errorf("Failed to load state: %w", err)) diags = diags.Append(fmt.Errorf("Failed to load state: %w", err))
return nil, diags return nil, diags

View File

@ -4,6 +4,7 @@
package command package command
import ( import (
"context"
"fmt" "fmt"
"path/filepath" "path/filepath"
"strings" "strings"
@ -99,7 +100,10 @@ func (c *ProvidersCommand) Run(args []string) int {
c.Ui.Error(fmt.Sprintf("Error selecting workspace: %s", err)) c.Ui.Error(fmt.Sprintf("Error selecting workspace: %s", err))
return 1 return 1
} }
s, err := b.StateMgr(env)
ctx := context.TODO()
s, err := b.StateMgr(ctx, env)
if err != nil { if err != nil {
c.Ui.Error(fmt.Sprintf("Failed to load state: %s", err)) c.Ui.Error(fmt.Sprintf("Failed to load state: %s", err))
return 1 return 1

View File

@ -336,8 +336,10 @@ func getStateFromPath(path string) (*statefile.File, error) {
// getStateFromBackend returns the State for the current workspace, if available. // getStateFromBackend returns the State for the current workspace, if available.
func getStateFromBackend(b backend.Backend, workspace string) (*statefile.File, error) { func getStateFromBackend(b backend.Backend, workspace string) (*statefile.File, error) {
ctx := context.TODO()
// Get the state store for the given workspace // Get the state store for the given workspace
stateStore, err := b.StateMgr(workspace) stateStore, err := b.StateMgr(ctx, workspace)
if err != nil { if err != nil {
return nil, fmt.Errorf("Failed to load state manager: %w", err) return nil, fmt.Errorf("Failed to load state manager: %w", err)
} }

View File

@ -4,6 +4,7 @@
package command package command
import ( import (
"context"
"fmt" "fmt"
"strings" "strings"
@ -53,7 +54,10 @@ func (c *StateListCommand) Run(args []string) int {
c.Ui.Error(fmt.Sprintf("Error selecting workspace: %s", err)) c.Ui.Error(fmt.Sprintf("Error selecting workspace: %s", err))
return 1 return 1
} }
stateMgr, err := b.StateMgr(env)
ctx := context.TODO()
stateMgr, err := b.StateMgr(ctx, env)
if err != nil { if err != nil {
c.Ui.Error(fmt.Sprintf(errStateLoadingState, err)) c.Ui.Error(fmt.Sprintf(errStateLoadingState, err))
return 1 return 1

View File

@ -4,6 +4,7 @@
package command package command
import ( import (
"context"
"fmt" "fmt"
"sort" "sort"
"time" "time"
@ -52,8 +53,10 @@ func (c *StateMeta) State() (statemgr.Full, error) {
return nil, fmt.Errorf("Error checking remote OpenTofu version") return nil, fmt.Errorf("Error checking remote OpenTofu version")
} }
ctx := context.TODO()
// Get the state // Get the state
s, err := b.StateMgr(workspace) s, err := b.StateMgr(ctx, workspace)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -5,6 +5,7 @@ package command
import ( import (
"bytes" "bytes"
"context"
"fmt" "fmt"
"strings" "strings"
@ -47,7 +48,10 @@ func (c *StatePullCommand) Run(args []string) int {
c.Ui.Error(fmt.Sprintf("Error selecting workspace: %s", err)) c.Ui.Error(fmt.Sprintf("Error selecting workspace: %s", err))
return 1 return 1
} }
stateMgr, err := b.StateMgr(env)
ctx := context.TODO()
stateMgr, err := b.StateMgr(ctx, env)
if err != nil { if err != nil {
c.Ui.Error(fmt.Sprintf(errStateLoadingState, err)) c.Ui.Error(fmt.Sprintf(errStateLoadingState, err))
return 1 return 1

View File

@ -4,6 +4,7 @@
package command package command
import ( import (
"context"
"fmt" "fmt"
"io" "io"
"os" "os"
@ -97,8 +98,10 @@ func (c *StatePushCommand) Run(args []string) int {
return 1 return 1
} }
ctx := context.TODO()
// Get the state manager for the currently-selected workspace // Get the state manager for the currently-selected workspace
stateMgr, err := b.StateMgr(workspace) stateMgr, err := b.StateMgr(ctx, workspace)
if err != nil { if err != nil {
c.Ui.Error(fmt.Sprintf("Failed to load destination state: %s", err)) c.Ui.Error(fmt.Sprintf("Failed to load destination state: %s", err))
return 1 return 1

View File

@ -5,6 +5,7 @@ package command
import ( import (
"bytes" "bytes"
"context"
"strings" "strings"
"testing" "testing"
@ -261,9 +262,11 @@ func TestStatePush_forceRemoteState(t *testing.T) {
t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter) t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter)
} }
ctx := context.Background()
// put a dummy state in place, so we have something to force // put a dummy state in place, so we have something to force
b := backend.TestBackendConfig(t, inmem.New(), nil) b := backend.TestBackendConfig(t, inmem.New(), nil)
sMgr, err := b.StateMgr("test") sMgr, err := b.StateMgr(ctx, "test")
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }

View File

@ -4,6 +4,7 @@
package command package command
import ( import (
"context"
"fmt" "fmt"
"os" "os"
"strings" "strings"
@ -109,7 +110,10 @@ func (c *StateShowCommand) Run(args []string) int {
c.Streams.Eprintf("Error selecting workspace: %s\n", err) c.Streams.Eprintf("Error selecting workspace: %s\n", err)
return 1 return 1
} }
stateMgr, err := b.StateMgr(env)
ctx := context.TODO()
stateMgr, err := b.StateMgr(ctx, env)
if err != nil { if err != nil {
c.Streams.Eprintln(fmt.Sprintf(errStateLoadingState, err)) c.Streams.Eprintln(fmt.Sprintf(errStateLoadingState, err))
return 1 return 1

View File

@ -4,6 +4,7 @@
package command package command
import ( import (
"context"
"fmt" "fmt"
"strings" "strings"
@ -88,8 +89,10 @@ func (c *TaintCommand) Run(args []string) int {
return 1 return 1
} }
ctx := context.TODO()
// Get the state // Get the state
stateMgr, err := b.StateMgr(workspace) stateMgr, err := b.StateMgr(ctx, workspace)
if err != nil { if err != nil {
c.Ui.Error(fmt.Sprintf("Failed to load state: %s", err)) c.Ui.Error(fmt.Sprintf("Failed to load state: %s", err))
return 1 return 1

View File

@ -74,7 +74,10 @@ func (c *UnlockCommand) Run(args []string) int {
c.Ui.Error(fmt.Sprintf("Error selecting workspace: %s", err)) c.Ui.Error(fmt.Sprintf("Error selecting workspace: %s", err))
return 1 return 1
} }
stateMgr, err := b.StateMgr(env)
ctx := context.TODO()
stateMgr, err := b.StateMgr(ctx, env)
if err != nil { if err != nil {
c.Ui.Error(fmt.Sprintf("Failed to load state: %s", err)) c.Ui.Error(fmt.Sprintf("Failed to load state: %s", err))
return 1 return 1

View File

@ -4,6 +4,7 @@
package command package command
import ( import (
"context"
"fmt" "fmt"
"strings" "strings"
@ -78,8 +79,10 @@ func (c *UntaintCommand) Run(args []string) int {
return 1 return 1
} }
ctx := context.TODO()
// Get the state // Get the state
stateMgr, err := b.StateMgr(workspace) stateMgr, err := b.StateMgr(ctx, workspace)
if err != nil { if err != nil {
c.Ui.Error(fmt.Sprintf("Failed to load state: %s", err)) c.Ui.Error(fmt.Sprintf("Failed to load state: %s", err))
return 1 return 1

View File

@ -4,6 +4,7 @@
package command package command
import ( import (
"context"
"os" "os"
"path/filepath" "path/filepath"
"strings" "strings"
@ -275,7 +276,7 @@ func TestWorkspace_createWithState(t *testing.T) {
} }
b := backend.TestBackendConfig(t, inmem.New(), nil) b := backend.TestBackendConfig(t, inmem.New(), nil)
sMgr, err := b.StateMgr(workspace) sMgr, err := b.StateMgr(context.Background(), workspace)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }

View File

@ -4,6 +4,7 @@
package command package command
import ( import (
"context"
"fmt" "fmt"
"strings" "strings"
"time" "time"
@ -104,8 +105,10 @@ func (c *WorkspaceDeleteCommand) Run(args []string) int {
return 1 return 1
} }
ctx := context.Background()
// we need the actual state to see if it's empty // we need the actual state to see if it's empty
stateMgr, err := b.StateMgr(workspace) stateMgr, err := b.StateMgr(ctx, workspace)
if err != nil { if err != nil {
c.Ui.Error(err.Error()) c.Ui.Error(err.Error())
return 1 return 1

View File

@ -4,6 +4,7 @@
package command package command
import ( import (
"context"
"fmt" "fmt"
"os" "os"
"strings" "strings"
@ -101,7 +102,8 @@ func (c *WorkspaceNewCommand) Run(args []string) int {
} }
} }
_, err = b.StateMgr(workspace) ctx := context.Background()
_, err = b.StateMgr(ctx, workspace)
if err != nil { if err != nil {
c.Ui.Error(err.Error()) c.Ui.Error(err.Error())
return 1 return 1
@ -122,7 +124,7 @@ func (c *WorkspaceNewCommand) Run(args []string) int {
} }
// load the new Backend state // load the new Backend state
stateMgr, err := b.StateMgr(workspace) stateMgr, err := b.StateMgr(ctx, workspace)
if err != nil { if err != nil {
c.Ui.Error(err.Error()) c.Ui.Error(err.Error())
return 1 return 1

View File

@ -4,6 +4,7 @@
package command package command
import ( import (
"context"
"fmt" "fmt"
"strings" "strings"
@ -102,10 +103,11 @@ func (c *WorkspaceSelectCommand) Run(args []string) int {
} }
var newState bool var newState bool
ctx := context.Background()
if !found { if !found {
if orCreate { if orCreate {
_, err = b.StateMgr(name) _, err = b.StateMgr(ctx, name)
if err != nil { if err != nil {
c.Ui.Error(err.Error()) c.Ui.Error(err.Error())
return 1 return 1