mirror of
https://github.com/opentofu/opentofu.git
synced 2025-02-25 18:45:20 -06:00
Integrate Encryption into State Backends (#1288)
Signed-off-by: Christian Mesh <christianmesh1@gmail.com>
This commit is contained in:
parent
ac3ed86617
commit
2f5dcd5c0a
@ -24,6 +24,7 @@ import (
|
||||
"github.com/opentofu/opentofu/internal/configs/configload"
|
||||
"github.com/opentofu/opentofu/internal/configs/configschema"
|
||||
"github.com/opentofu/opentofu/internal/depsfile"
|
||||
"github.com/opentofu/opentofu/internal/encryption"
|
||||
"github.com/opentofu/opentofu/internal/plans"
|
||||
"github.com/opentofu/opentofu/internal/plans/planfile"
|
||||
"github.com/opentofu/opentofu/internal/states"
|
||||
@ -54,7 +55,7 @@ var (
|
||||
)
|
||||
|
||||
// InitFn is used to initialize a new backend.
|
||||
type InitFn func() Backend
|
||||
type InitFn func(encryption.StateEncryption) Backend
|
||||
|
||||
// Backend is the minimal interface that must be implemented to enable OpenTofu.
|
||||
type Backend interface {
|
||||
|
@ -9,13 +9,14 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/opentofu/opentofu/internal/backend/remote-state/inmem"
|
||||
"github.com/opentofu/opentofu/internal/encryption"
|
||||
"github.com/zclconf/go-cty/cty"
|
||||
)
|
||||
|
||||
func TestDeprecateBackend(t *testing.T) {
|
||||
deprecateMessage := "deprecated backend"
|
||||
deprecatedBackend := deprecateBackend(
|
||||
inmem.New(),
|
||||
inmem.New(encryption.StateEncryptionDisabled()),
|
||||
deprecateMessage,
|
||||
)
|
||||
|
||||
|
@ -12,6 +12,7 @@ import (
|
||||
|
||||
"github.com/hashicorp/terraform-svchost/disco"
|
||||
"github.com/opentofu/opentofu/internal/backend"
|
||||
"github.com/opentofu/opentofu/internal/encryption"
|
||||
"github.com/opentofu/opentofu/internal/tfdiags"
|
||||
"github.com/zclconf/go-cty/cty"
|
||||
|
||||
@ -54,24 +55,24 @@ func Init(services *disco.Disco) {
|
||||
defer backendsLock.Unlock()
|
||||
|
||||
backends = map[string]backend.InitFn{
|
||||
"local": func() backend.Backend { return backendLocal.New() },
|
||||
"remote": func() backend.Backend { return backendRemote.New(services) },
|
||||
"local": func(enc encryption.StateEncryption) backend.Backend { return backendLocal.New(enc) },
|
||||
"remote": func(enc encryption.StateEncryption) backend.Backend { return backendRemote.New(services, enc) },
|
||||
|
||||
// Remote State backends.
|
||||
"azurerm": func() backend.Backend { return backendAzure.New() },
|
||||
"consul": func() backend.Backend { return backendConsul.New() },
|
||||
"cos": func() backend.Backend { return backendCos.New() },
|
||||
"gcs": func() backend.Backend { return backendGCS.New() },
|
||||
"http": func() backend.Backend { return backendHTTP.New() },
|
||||
"inmem": func() backend.Backend { return backendInmem.New() },
|
||||
"kubernetes": func() backend.Backend { return backendKubernetes.New() },
|
||||
"oss": func() backend.Backend { return backendOSS.New() },
|
||||
"pg": func() backend.Backend { return backendPg.New() },
|
||||
"s3": func() backend.Backend { return backendS3.New() },
|
||||
"azurerm": func(enc encryption.StateEncryption) backend.Backend { return backendAzure.New(enc) },
|
||||
"consul": func(enc encryption.StateEncryption) backend.Backend { return backendConsul.New(enc) },
|
||||
"cos": func(enc encryption.StateEncryption) backend.Backend { return backendCos.New(enc) },
|
||||
"gcs": func(enc encryption.StateEncryption) backend.Backend { return backendGCS.New(enc) },
|
||||
"http": func(enc encryption.StateEncryption) backend.Backend { return backendHTTP.New(enc) },
|
||||
"inmem": func(enc encryption.StateEncryption) backend.Backend { return backendInmem.New(enc) },
|
||||
"kubernetes": func(enc encryption.StateEncryption) backend.Backend { return backendKubernetes.New(enc) },
|
||||
"oss": func(enc encryption.StateEncryption) backend.Backend { return backendOSS.New(enc) },
|
||||
"pg": func(enc encryption.StateEncryption) backend.Backend { return backendPg.New(enc) },
|
||||
"s3": func(enc encryption.StateEncryption) backend.Backend { return backendS3.New(enc) },
|
||||
|
||||
// Terraform Cloud 'backend'
|
||||
// This is an implementation detail only, used for the cloud package
|
||||
"cloud": func() backend.Backend { return backendCloud.New(services) },
|
||||
"cloud": func(enc encryption.StateEncryption) backend.Backend { return backendCloud.New(services, enc) },
|
||||
}
|
||||
|
||||
RemovedBackends = map[string]string{
|
||||
|
@ -8,6 +8,8 @@ package init
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/opentofu/opentofu/internal/encryption"
|
||||
)
|
||||
|
||||
func TestInit_backend(t *testing.T) {
|
||||
@ -36,7 +38,7 @@ func TestInit_backend(t *testing.T) {
|
||||
if f == nil {
|
||||
t.Fatalf("backend %q is not present; should be", b.Name)
|
||||
}
|
||||
bType := reflect.TypeOf(f()).String()
|
||||
bType := reflect.TypeOf(f(encryption.StateEncryptionDisabled())).String()
|
||||
if bType != b.Type {
|
||||
t.Fatalf("expected backend %q to be %q, got: %q", b.Name, b.Type, bType)
|
||||
}
|
||||
|
@ -18,6 +18,7 @@ import (
|
||||
"github.com/opentofu/opentofu/internal/backend"
|
||||
"github.com/opentofu/opentofu/internal/command/views"
|
||||
"github.com/opentofu/opentofu/internal/configs/configschema"
|
||||
"github.com/opentofu/opentofu/internal/encryption"
|
||||
"github.com/opentofu/opentofu/internal/logging"
|
||||
"github.com/opentofu/opentofu/internal/states/statemgr"
|
||||
"github.com/opentofu/opentofu/internal/tfdiags"
|
||||
@ -89,20 +90,28 @@ type Local struct {
|
||||
|
||||
// opLock locks operations
|
||||
opLock sync.Mutex
|
||||
|
||||
encryption encryption.StateEncryption
|
||||
}
|
||||
|
||||
var _ backend.Backend = (*Local)(nil)
|
||||
|
||||
// New returns a new initialized local backend.
|
||||
func New() *Local {
|
||||
return NewWithBackend(nil)
|
||||
func New(enc encryption.StateEncryption) *Local {
|
||||
return &Local{
|
||||
encryption: enc,
|
||||
}
|
||||
}
|
||||
|
||||
// NewWithBackend returns a new local backend initialized with a
|
||||
// dedicated backend for non-enhanced behavior.
|
||||
func NewWithBackend(backend backend.Backend) *Local {
|
||||
func NewWithBackend(backend backend.Backend, enc encryption.StateEncryption) *Local {
|
||||
if backend == nil && enc == nil {
|
||||
panic("either backend or encryption required for backend.Local initialization")
|
||||
}
|
||||
return &Local{
|
||||
Backend: backend,
|
||||
Backend: backend,
|
||||
encryption: enc,
|
||||
}
|
||||
}
|
||||
|
||||
@ -257,7 +266,7 @@ func (b *Local) StateMgr(name string) (statemgr.Full, error) {
|
||||
statePath, stateOutPath, backupPath := b.StatePaths(name)
|
||||
log.Printf("[TRACE] backend/local: state manager for workspace %q will:\n - read initial snapshot from %s\n - write new snapshots to %s\n - create any backup at %s", name, statePath, stateOutPath, backupPath)
|
||||
|
||||
s := statemgr.NewFilesystemBetweenPaths(statePath, stateOutPath)
|
||||
s := statemgr.NewFilesystemBetweenPaths(statePath, stateOutPath, b.encryption)
|
||||
if backupPath != "" {
|
||||
s.SetBackupPath(backupPath)
|
||||
}
|
||||
|
@ -295,7 +295,7 @@ func (b *Local) backupStateForError(stateFile *statefile.File, err error, view v
|
||||
fmt.Sprintf("Error saving state: %s", err),
|
||||
))
|
||||
|
||||
local := statemgr.NewFilesystem("errored.tfstate")
|
||||
local := statemgr.NewFilesystem("errored.tfstate", b.encryption)
|
||||
writeErr := local.WriteStateForMigration(stateFile, true)
|
||||
if writeErr != nil {
|
||||
diags = diags.Append(tfdiags.Sourceless(
|
||||
@ -309,7 +309,7 @@ func (b *Local) backupStateForError(stateFile *statefile.File, err error, view v
|
||||
// UX, so we should definitely avoid doing this if at all possible,
|
||||
// but at least the user has _some_ path to recover if we end up
|
||||
// here for some reason.
|
||||
if dumpErr := view.EmergencyDumpState(stateFile); dumpErr != nil {
|
||||
if dumpErr := view.EmergencyDumpState(stateFile, b.encryption); dumpErr != nil {
|
||||
diags = diags.Append(tfdiags.Sourceless(
|
||||
tfdiags.Error,
|
||||
"Failed to serialize state",
|
||||
|
@ -23,6 +23,7 @@ import (
|
||||
"github.com/opentofu/opentofu/internal/command/views"
|
||||
"github.com/opentofu/opentofu/internal/configs/configschema"
|
||||
"github.com/opentofu/opentofu/internal/depsfile"
|
||||
"github.com/opentofu/opentofu/internal/encryption"
|
||||
"github.com/opentofu/opentofu/internal/initwd"
|
||||
"github.com/opentofu/opentofu/internal/plans"
|
||||
"github.com/opentofu/opentofu/internal/providers"
|
||||
@ -351,7 +352,7 @@ type backendWithFailingState struct {
|
||||
|
||||
func (b *backendWithFailingState) StateMgr(name string) (statemgr.Full, error) {
|
||||
return &failingState{
|
||||
statemgr.NewFilesystem("failing-state.tfstate"),
|
||||
statemgr.NewFilesystem("failing-state.tfstate", encryption.StateEncryptionDisabled()),
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
@ -136,7 +136,7 @@ func TestLocalRun_stalePlan(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error creating state file %s: %s", b.StatePath, err)
|
||||
}
|
||||
if err := statefile.Write(statefile.New(states.NewState(), "boop", 3), sf); err != nil {
|
||||
if err := statefile.Write(statefile.New(states.NewState(), "boop", 3), sf, encryption.StateEncryptionDisabled()); err != nil {
|
||||
t.Fatalf("unexpected error writing state file: %s", err)
|
||||
}
|
||||
|
||||
|
@ -14,19 +14,20 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/opentofu/opentofu/internal/backend"
|
||||
"github.com/opentofu/opentofu/internal/encryption"
|
||||
"github.com/opentofu/opentofu/internal/states/statefile"
|
||||
"github.com/opentofu/opentofu/internal/states/statemgr"
|
||||
)
|
||||
|
||||
func TestLocal_impl(t *testing.T) {
|
||||
var _ backend.Enhanced = New()
|
||||
var _ backend.Local = New()
|
||||
var _ backend.CLI = New()
|
||||
var _ backend.Enhanced = New(encryption.StateEncryptionDisabled())
|
||||
var _ backend.Local = New(encryption.StateEncryptionDisabled())
|
||||
var _ backend.CLI = New(encryption.StateEncryptionDisabled())
|
||||
}
|
||||
|
||||
func TestLocal_backend(t *testing.T) {
|
||||
testTmpDir(t)
|
||||
b := New()
|
||||
b := New(encryption.StateEncryptionDisabled())
|
||||
backend.TestBackendStates(t, b)
|
||||
backend.TestBackendStateLocks(t, b, b)
|
||||
}
|
||||
@ -39,7 +40,7 @@ func checkState(t *testing.T, path, expected string) {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
|
||||
state, err := statefile.Read(f)
|
||||
state, err := statefile.Read(f, encryption.StateEncryptionDisabled())
|
||||
f.Close()
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
@ -53,7 +54,7 @@ func checkState(t *testing.T, path, expected string) {
|
||||
}
|
||||
|
||||
func TestLocal_StatePaths(t *testing.T) {
|
||||
b := New()
|
||||
b := New(encryption.StateEncryptionDisabled())
|
||||
|
||||
// Test the defaults
|
||||
path, out, back := b.StatePaths("")
|
||||
@ -98,7 +99,7 @@ func TestLocal_addAndRemoveStates(t *testing.T) {
|
||||
dflt := backend.DefaultStateName
|
||||
expectedStates := []string{dflt}
|
||||
|
||||
b := New()
|
||||
b := New(encryption.StateEncryptionDisabled())
|
||||
states, err := b.Workspaces()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@ -190,7 +191,7 @@ func (b *testDelegateBackend) StateMgr(name string) (statemgr.Full, error) {
|
||||
if b.stateErr {
|
||||
return nil, errTestDelegateState
|
||||
}
|
||||
s := statemgr.NewFilesystem("terraform.tfstate")
|
||||
s := statemgr.NewFilesystem("terraform.tfstate", encryption.StateEncryptionDisabled())
|
||||
return s, nil
|
||||
}
|
||||
|
||||
@ -215,7 +216,7 @@ func TestLocal_multiStateBackend(t *testing.T) {
|
||||
stateErr: true,
|
||||
statesErr: true,
|
||||
deleteErr: true,
|
||||
})
|
||||
}, nil)
|
||||
|
||||
if _, err := b.StateMgr("test"); err != errTestDelegateState {
|
||||
t.Fatal("expected errTestDelegateState, got:", err)
|
||||
|
@ -14,6 +14,7 @@ import (
|
||||
"github.com/opentofu/opentofu/internal/addrs"
|
||||
"github.com/opentofu/opentofu/internal/backend"
|
||||
"github.com/opentofu/opentofu/internal/configs/configschema"
|
||||
"github.com/opentofu/opentofu/internal/encryption"
|
||||
"github.com/opentofu/opentofu/internal/providers"
|
||||
"github.com/opentofu/opentofu/internal/states"
|
||||
"github.com/opentofu/opentofu/internal/states/statemgr"
|
||||
@ -32,7 +33,7 @@ func TestLocal(t *testing.T) *Local {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
local := New()
|
||||
local := New(encryption.StateEncryptionDisabled())
|
||||
local.StatePath = filepath.Join(tempDir, "state.tfstate")
|
||||
local.StateOutPath = filepath.Join(tempDir, "state.tfstate")
|
||||
local.StateBackupPath = filepath.Join(tempDir, "state.tfstate.bak")
|
||||
@ -115,8 +116,8 @@ type TestLocalSingleState struct {
|
||||
|
||||
// TestNewLocalSingle is a factory for creating a TestLocalSingleState.
|
||||
// This function matches the signature required for backend/init.
|
||||
func TestNewLocalSingle() backend.Backend {
|
||||
return &TestLocalSingleState{Local: New()}
|
||||
func TestNewLocalSingle(enc encryption.StateEncryption) backend.Backend {
|
||||
return &TestLocalSingleState{Local: New(encryption.StateEncryptionDisabled())}
|
||||
}
|
||||
|
||||
func (b *TestLocalSingleState) Workspaces() ([]string, error) {
|
||||
@ -145,8 +146,8 @@ type TestLocalNoDefaultState struct {
|
||||
|
||||
// TestNewLocalNoDefault is a factory for creating a TestLocalNoDefaultState.
|
||||
// This function matches the signature required for backend/init.
|
||||
func TestNewLocalNoDefault() backend.Backend {
|
||||
return &TestLocalNoDefaultState{Local: New()}
|
||||
func TestNewLocalNoDefault(enc encryption.StateEncryption) backend.Backend {
|
||||
return &TestLocalNoDefaultState{Local: New(encryption.StateEncryptionDisabled())}
|
||||
}
|
||||
|
||||
func (b *TestLocalNoDefaultState) Workspaces() ([]string, error) {
|
||||
@ -182,7 +183,7 @@ func (b *TestLocalNoDefaultState) StateMgr(name string) (statemgr.Full, error) {
|
||||
func testStateFile(t *testing.T, path string, s *states.State) {
|
||||
t.Helper()
|
||||
|
||||
if err := statemgr.WriteAndPersist(statemgr.NewFilesystem(path), s, nil); err != nil {
|
||||
if err := statemgr.WriteAndPersist(statemgr.NewFilesystem(path, encryption.StateEncryptionDisabled()), s, nil); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
@ -10,11 +10,12 @@ import (
|
||||
"fmt"
|
||||
|
||||
"github.com/opentofu/opentofu/internal/backend"
|
||||
"github.com/opentofu/opentofu/internal/encryption"
|
||||
"github.com/opentofu/opentofu/internal/legacy/helper/schema"
|
||||
)
|
||||
|
||||
// New creates a new backend for Azure remote state.
|
||||
func New() backend.Backend {
|
||||
func New(enc encryption.StateEncryption) backend.Backend {
|
||||
s := &schema.Backend{
|
||||
Schema: map[string]*schema.Schema{
|
||||
"storage_account_name": {
|
||||
@ -182,13 +183,14 @@ func New() backend.Backend {
|
||||
},
|
||||
}
|
||||
|
||||
result := &Backend{Backend: s}
|
||||
result := &Backend{Backend: s, encryption: enc}
|
||||
result.Backend.ConfigureFunc = result.configure
|
||||
return result
|
||||
}
|
||||
|
||||
type Backend struct {
|
||||
*schema.Backend
|
||||
encryption encryption.StateEncryption
|
||||
|
||||
// The fields below are set from configure
|
||||
armClient *ArmClient
|
||||
|
@ -98,7 +98,7 @@ func (b *Backend) StateMgr(name string) (statemgr.Full, error) {
|
||||
snapshot: b.snapshot,
|
||||
}
|
||||
|
||||
stateMgr := &remote.State{Client: client}
|
||||
stateMgr := remote.NewState(client, b.encryption)
|
||||
|
||||
// Grab the value
|
||||
if err := stateMgr.RefreshState(); err != nil {
|
||||
|
@ -11,6 +11,7 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/opentofu/opentofu/internal/backend"
|
||||
"github.com/opentofu/opentofu/internal/encryption"
|
||||
"github.com/opentofu/opentofu/internal/legacy/helper/acctest"
|
||||
)
|
||||
|
||||
@ -31,7 +32,7 @@ func TestBackendConfig(t *testing.T) {
|
||||
"access_key": "QUNDRVNTX0tFWQ0K",
|
||||
}
|
||||
|
||||
b := backend.TestBackendConfig(t, New(), backend.TestWrapConfig(config)).(*Backend)
|
||||
b := backend.TestBackendConfig(t, New(encryption.StateEncryptionDisabled()), backend.TestWrapConfig(config)).(*Backend)
|
||||
|
||||
if b.containerName != "tfcontainer" {
|
||||
t.Fatalf("Incorrect bucketName was populated")
|
||||
@ -58,7 +59,7 @@ func TestAccBackendAccessKeyBasic(t *testing.T) {
|
||||
t.Fatalf("Error creating Test Resources: %q", err)
|
||||
}
|
||||
|
||||
b := backend.TestBackendConfig(t, New(), backend.TestWrapConfig(map[string]interface{}{
|
||||
b := backend.TestBackendConfig(t, New(encryption.StateEncryptionDisabled()), backend.TestWrapConfig(map[string]interface{}{
|
||||
"storage_account_name": res.storageAccountName,
|
||||
"container_name": res.storageContainerName,
|
||||
"key": res.storageKeyName,
|
||||
@ -88,7 +89,7 @@ func TestAccBackendSASTokenBasic(t *testing.T) {
|
||||
t.Fatalf("Error building SAS Token: %+v", err)
|
||||
}
|
||||
|
||||
b := backend.TestBackendConfig(t, New(), backend.TestWrapConfig(map[string]interface{}{
|
||||
b := backend.TestBackendConfig(t, New(encryption.StateEncryptionDisabled()), backend.TestWrapConfig(map[string]interface{}{
|
||||
"storage_account_name": res.storageAccountName,
|
||||
"container_name": res.storageContainerName,
|
||||
"key": res.storageKeyName,
|
||||
@ -113,7 +114,7 @@ func TestAccBackendOIDCBasic(t *testing.T) {
|
||||
t.Fatalf("Error creating Test Resources: %q", err)
|
||||
}
|
||||
|
||||
b := backend.TestBackendConfig(t, New(), backend.TestWrapConfig(map[string]interface{}{
|
||||
b := backend.TestBackendConfig(t, New(encryption.StateEncryptionDisabled()), backend.TestWrapConfig(map[string]interface{}{
|
||||
"storage_account_name": res.storageAccountName,
|
||||
"container_name": res.storageContainerName,
|
||||
"key": res.storageKeyName,
|
||||
@ -141,7 +142,7 @@ func TestAccBackendManagedServiceIdentityBasic(t *testing.T) {
|
||||
t.Fatalf("Error creating Test Resources: %q", err)
|
||||
}
|
||||
|
||||
b := backend.TestBackendConfig(t, New(), backend.TestWrapConfig(map[string]interface{}{
|
||||
b := backend.TestBackendConfig(t, New(encryption.StateEncryptionDisabled()), backend.TestWrapConfig(map[string]interface{}{
|
||||
"storage_account_name": res.storageAccountName,
|
||||
"container_name": res.storageContainerName,
|
||||
"key": res.storageKeyName,
|
||||
@ -176,7 +177,7 @@ func TestAccBackendServicePrincipalClientCertificateBasic(t *testing.T) {
|
||||
t.Fatalf("Error creating Test Resources: %q", err)
|
||||
}
|
||||
|
||||
b := backend.TestBackendConfig(t, New(), backend.TestWrapConfig(map[string]interface{}{
|
||||
b := backend.TestBackendConfig(t, New(encryption.StateEncryptionDisabled()), backend.TestWrapConfig(map[string]interface{}{
|
||||
"storage_account_name": res.storageAccountName,
|
||||
"container_name": res.storageContainerName,
|
||||
"key": res.storageKeyName,
|
||||
@ -206,7 +207,7 @@ func TestAccBackendServicePrincipalClientSecretBasic(t *testing.T) {
|
||||
t.Fatalf("Error creating Test Resources: %q", err)
|
||||
}
|
||||
|
||||
b := backend.TestBackendConfig(t, New(), backend.TestWrapConfig(map[string]interface{}{
|
||||
b := backend.TestBackendConfig(t, New(encryption.StateEncryptionDisabled()), backend.TestWrapConfig(map[string]interface{}{
|
||||
"storage_account_name": res.storageAccountName,
|
||||
"container_name": res.storageContainerName,
|
||||
"key": res.storageKeyName,
|
||||
@ -242,7 +243,7 @@ func TestAccBackendServicePrincipalClientSecretCustomEndpoint(t *testing.T) {
|
||||
t.Fatalf("Error creating Test Resources: %q", err)
|
||||
}
|
||||
|
||||
b := backend.TestBackendConfig(t, New(), backend.TestWrapConfig(map[string]interface{}{
|
||||
b := backend.TestBackendConfig(t, New(encryption.StateEncryptionDisabled()), backend.TestWrapConfig(map[string]interface{}{
|
||||
"storage_account_name": res.storageAccountName,
|
||||
"container_name": res.storageContainerName,
|
||||
"key": res.storageKeyName,
|
||||
@ -271,7 +272,7 @@ func TestAccBackendAccessKeyLocked(t *testing.T) {
|
||||
t.Fatalf("Error creating Test Resources: %q", err)
|
||||
}
|
||||
|
||||
b1 := backend.TestBackendConfig(t, New(), backend.TestWrapConfig(map[string]interface{}{
|
||||
b1 := backend.TestBackendConfig(t, New(encryption.StateEncryptionDisabled()), backend.TestWrapConfig(map[string]interface{}{
|
||||
"storage_account_name": res.storageAccountName,
|
||||
"container_name": res.storageContainerName,
|
||||
"key": res.storageKeyName,
|
||||
@ -280,7 +281,7 @@ func TestAccBackendAccessKeyLocked(t *testing.T) {
|
||||
"endpoint": os.Getenv("ARM_ENDPOINT"),
|
||||
})).(*Backend)
|
||||
|
||||
b2 := backend.TestBackendConfig(t, New(), backend.TestWrapConfig(map[string]interface{}{
|
||||
b2 := backend.TestBackendConfig(t, New(encryption.StateEncryptionDisabled()), backend.TestWrapConfig(map[string]interface{}{
|
||||
"storage_account_name": res.storageAccountName,
|
||||
"container_name": res.storageContainerName,
|
||||
"key": res.storageKeyName,
|
||||
@ -309,7 +310,7 @@ func TestAccBackendServicePrincipalLocked(t *testing.T) {
|
||||
t.Fatalf("Error creating Test Resources: %q", err)
|
||||
}
|
||||
|
||||
b1 := backend.TestBackendConfig(t, New(), backend.TestWrapConfig(map[string]interface{}{
|
||||
b1 := backend.TestBackendConfig(t, New(encryption.StateEncryptionDisabled()), backend.TestWrapConfig(map[string]interface{}{
|
||||
"storage_account_name": res.storageAccountName,
|
||||
"container_name": res.storageContainerName,
|
||||
"key": res.storageKeyName,
|
||||
@ -322,7 +323,7 @@ func TestAccBackendServicePrincipalLocked(t *testing.T) {
|
||||
"endpoint": os.Getenv("ARM_ENDPOINT"),
|
||||
})).(*Backend)
|
||||
|
||||
b2 := backend.TestBackendConfig(t, New(), backend.TestWrapConfig(map[string]interface{}{
|
||||
b2 := backend.TestBackendConfig(t, New(encryption.StateEncryptionDisabled()), backend.TestWrapConfig(map[string]interface{}{
|
||||
"storage_account_name": res.storageAccountName,
|
||||
"container_name": res.storageContainerName,
|
||||
"key": res.storageKeyName,
|
||||
|
@ -11,6 +11,7 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/opentofu/opentofu/internal/backend"
|
||||
"github.com/opentofu/opentofu/internal/encryption"
|
||||
"github.com/opentofu/opentofu/internal/legacy/helper/acctest"
|
||||
"github.com/opentofu/opentofu/internal/states/remote"
|
||||
"github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs"
|
||||
@ -34,7 +35,7 @@ func TestRemoteClientAccessKeyBasic(t *testing.T) {
|
||||
t.Fatalf("Error creating Test Resources: %q", err)
|
||||
}
|
||||
|
||||
b := backend.TestBackendConfig(t, New(), backend.TestWrapConfig(map[string]interface{}{
|
||||
b := backend.TestBackendConfig(t, New(encryption.StateEncryptionDisabled()), backend.TestWrapConfig(map[string]interface{}{
|
||||
"storage_account_name": res.storageAccountName,
|
||||
"container_name": res.storageContainerName,
|
||||
"key": res.storageKeyName,
|
||||
@ -64,7 +65,7 @@ func TestRemoteClientManagedServiceIdentityBasic(t *testing.T) {
|
||||
t.Fatalf("Error creating Test Resources: %q", err)
|
||||
}
|
||||
|
||||
b := backend.TestBackendConfig(t, New(), backend.TestWrapConfig(map[string]interface{}{
|
||||
b := backend.TestBackendConfig(t, New(encryption.StateEncryptionDisabled()), backend.TestWrapConfig(map[string]interface{}{
|
||||
"storage_account_name": res.storageAccountName,
|
||||
"container_name": res.storageContainerName,
|
||||
"key": res.storageKeyName,
|
||||
@ -102,7 +103,7 @@ func TestRemoteClientSasTokenBasic(t *testing.T) {
|
||||
t.Fatalf("Error building SAS Token: %+v", err)
|
||||
}
|
||||
|
||||
b := backend.TestBackendConfig(t, New(), backend.TestWrapConfig(map[string]interface{}{
|
||||
b := backend.TestBackendConfig(t, New(encryption.StateEncryptionDisabled()), backend.TestWrapConfig(map[string]interface{}{
|
||||
"storage_account_name": res.storageAccountName,
|
||||
"container_name": res.storageContainerName,
|
||||
"key": res.storageKeyName,
|
||||
@ -132,7 +133,7 @@ func TestRemoteClientServicePrincipalBasic(t *testing.T) {
|
||||
t.Fatalf("Error creating Test Resources: %q", err)
|
||||
}
|
||||
|
||||
b := backend.TestBackendConfig(t, New(), backend.TestWrapConfig(map[string]interface{}{
|
||||
b := backend.TestBackendConfig(t, New(encryption.StateEncryptionDisabled()), backend.TestWrapConfig(map[string]interface{}{
|
||||
"storage_account_name": res.storageAccountName,
|
||||
"container_name": res.storageContainerName,
|
||||
"key": res.storageKeyName,
|
||||
@ -166,7 +167,7 @@ func TestRemoteClientAccessKeyLocks(t *testing.T) {
|
||||
t.Fatalf("Error creating Test Resources: %q", err)
|
||||
}
|
||||
|
||||
b1 := backend.TestBackendConfig(t, New(), backend.TestWrapConfig(map[string]interface{}{
|
||||
b1 := backend.TestBackendConfig(t, New(encryption.StateEncryptionDisabled()), backend.TestWrapConfig(map[string]interface{}{
|
||||
"storage_account_name": res.storageAccountName,
|
||||
"container_name": res.storageContainerName,
|
||||
"key": res.storageKeyName,
|
||||
@ -175,7 +176,7 @@ func TestRemoteClientAccessKeyLocks(t *testing.T) {
|
||||
"endpoint": os.Getenv("ARM_ENDPOINT"),
|
||||
})).(*Backend)
|
||||
|
||||
b2 := backend.TestBackendConfig(t, New(), backend.TestWrapConfig(map[string]interface{}{
|
||||
b2 := backend.TestBackendConfig(t, New(encryption.StateEncryptionDisabled()), backend.TestWrapConfig(map[string]interface{}{
|
||||
"storage_account_name": res.storageAccountName,
|
||||
"container_name": res.storageContainerName,
|
||||
"key": res.storageKeyName,
|
||||
@ -210,7 +211,7 @@ func TestRemoteClientServicePrincipalLocks(t *testing.T) {
|
||||
t.Fatalf("Error creating Test Resources: %q", err)
|
||||
}
|
||||
|
||||
b1 := backend.TestBackendConfig(t, New(), backend.TestWrapConfig(map[string]interface{}{
|
||||
b1 := backend.TestBackendConfig(t, New(encryption.StateEncryptionDisabled()), backend.TestWrapConfig(map[string]interface{}{
|
||||
"storage_account_name": res.storageAccountName,
|
||||
"container_name": res.storageContainerName,
|
||||
"key": res.storageKeyName,
|
||||
@ -223,7 +224,7 @@ func TestRemoteClientServicePrincipalLocks(t *testing.T) {
|
||||
"endpoint": os.Getenv("ARM_ENDPOINT"),
|
||||
})).(*Backend)
|
||||
|
||||
b2 := backend.TestBackendConfig(t, New(), backend.TestWrapConfig(map[string]interface{}{
|
||||
b2 := backend.TestBackendConfig(t, New(encryption.StateEncryptionDisabled()), backend.TestWrapConfig(map[string]interface{}{
|
||||
"storage_account_name": res.storageAccountName,
|
||||
"container_name": res.storageContainerName,
|
||||
"key": res.storageKeyName,
|
||||
|
@ -13,11 +13,12 @@ import (
|
||||
|
||||
consulapi "github.com/hashicorp/consul/api"
|
||||
"github.com/opentofu/opentofu/internal/backend"
|
||||
"github.com/opentofu/opentofu/internal/encryption"
|
||||
"github.com/opentofu/opentofu/internal/legacy/helper/schema"
|
||||
)
|
||||
|
||||
// New creates a new backend for Consul remote state.
|
||||
func New() backend.Backend {
|
||||
func New(enc encryption.StateEncryption) backend.Backend {
|
||||
s := &schema.Backend{
|
||||
Schema: map[string]*schema.Schema{
|
||||
"path": &schema.Schema{
|
||||
@ -98,13 +99,14 @@ func New() backend.Backend {
|
||||
},
|
||||
}
|
||||
|
||||
result := &Backend{Backend: s}
|
||||
result := &Backend{Backend: s, encryption: enc}
|
||||
result.Backend.ConfigureFunc = result.configure
|
||||
return result
|
||||
}
|
||||
|
||||
type Backend struct {
|
||||
*schema.Backend
|
||||
encryption encryption.StateEncryption
|
||||
|
||||
// The fields below are set from configure
|
||||
client *consulapi.Client
|
||||
|
@ -76,14 +76,15 @@ func (b *Backend) StateMgr(name string) (statemgr.Full, error) {
|
||||
gzip := b.configData.Get("gzip").(bool)
|
||||
|
||||
// Build the state client
|
||||
var stateMgr = &remote.State{
|
||||
Client: &RemoteClient{
|
||||
var stateMgr = remote.NewState(
|
||||
&RemoteClient{
|
||||
Client: b.client,
|
||||
Path: path,
|
||||
GZip: gzip,
|
||||
lockState: b.lock,
|
||||
},
|
||||
}
|
||||
b.encryption,
|
||||
)
|
||||
|
||||
if !b.lock {
|
||||
stateMgr.DisableLocks()
|
||||
|
@ -15,6 +15,7 @@ import (
|
||||
|
||||
"github.com/hashicorp/consul/sdk/testutil"
|
||||
"github.com/opentofu/opentofu/internal/backend"
|
||||
"github.com/opentofu/opentofu/internal/encryption"
|
||||
)
|
||||
|
||||
func TestBackend_impl(t *testing.T) {
|
||||
@ -56,12 +57,12 @@ func TestBackend(t *testing.T) {
|
||||
path := fmt.Sprintf("tf-unit/%s", time.Now().String())
|
||||
|
||||
// Get the backend. We need two to test locking.
|
||||
b1 := backend.TestBackendConfig(t, New(), backend.TestWrapConfig(map[string]interface{}{
|
||||
b1 := backend.TestBackendConfig(t, New(encryption.StateEncryptionDisabled()), backend.TestWrapConfig(map[string]interface{}{
|
||||
"address": srv.HTTPAddr,
|
||||
"path": path,
|
||||
}))
|
||||
|
||||
b2 := backend.TestBackendConfig(t, New(), backend.TestWrapConfig(map[string]interface{}{
|
||||
b2 := backend.TestBackendConfig(t, New(encryption.StateEncryptionDisabled()), backend.TestWrapConfig(map[string]interface{}{
|
||||
"address": srv.HTTPAddr,
|
||||
"path": path,
|
||||
}))
|
||||
@ -78,13 +79,13 @@ func TestBackend_lockDisabled(t *testing.T) {
|
||||
path := fmt.Sprintf("tf-unit/%s", time.Now().String())
|
||||
|
||||
// Get the backend. We need two to test locking.
|
||||
b1 := backend.TestBackendConfig(t, New(), backend.TestWrapConfig(map[string]interface{}{
|
||||
b1 := backend.TestBackendConfig(t, New(encryption.StateEncryptionDisabled()), backend.TestWrapConfig(map[string]interface{}{
|
||||
"address": srv.HTTPAddr,
|
||||
"path": path,
|
||||
"lock": false,
|
||||
}))
|
||||
|
||||
b2 := backend.TestBackendConfig(t, New(), backend.TestWrapConfig(map[string]interface{}{
|
||||
b2 := backend.TestBackendConfig(t, New(encryption.StateEncryptionDisabled()), backend.TestWrapConfig(map[string]interface{}{
|
||||
"address": srv.HTTPAddr,
|
||||
"path": path + "different", // Diff so locking test would fail if it was locking
|
||||
"lock": false,
|
||||
@ -100,7 +101,7 @@ func TestBackend_gzip(t *testing.T) {
|
||||
defer func() { _ = srv.Stop() }()
|
||||
|
||||
// Get the backend
|
||||
b := backend.TestBackendConfig(t, New(), backend.TestWrapConfig(map[string]interface{}{
|
||||
b := backend.TestBackendConfig(t, New(encryption.StateEncryptionDisabled()), backend.TestWrapConfig(map[string]interface{}{
|
||||
"address": srv.HTTPAddr,
|
||||
"path": fmt.Sprintf("tf-unit/%s", time.Now().String()),
|
||||
"gzip": true,
|
||||
|
@ -19,6 +19,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/opentofu/opentofu/internal/backend"
|
||||
"github.com/opentofu/opentofu/internal/encryption"
|
||||
"github.com/opentofu/opentofu/internal/states/remote"
|
||||
"github.com/opentofu/opentofu/internal/states/statemgr"
|
||||
)
|
||||
@ -40,7 +41,7 @@ func TestRemoteClient(t *testing.T) {
|
||||
for _, path := range testCases {
|
||||
t.Run(path, func(*testing.T) {
|
||||
// Get the backend
|
||||
b := backend.TestBackendConfig(t, New(), backend.TestWrapConfig(map[string]interface{}{
|
||||
b := backend.TestBackendConfig(t, New(encryption.StateEncryptionDisabled()), backend.TestWrapConfig(map[string]interface{}{
|
||||
"address": srv.HTTPAddr,
|
||||
"path": path,
|
||||
}))
|
||||
@ -65,7 +66,7 @@ func TestRemoteClient_gzipUpgrade(t *testing.T) {
|
||||
statePath := fmt.Sprintf("tf-unit/%s", time.Now().String())
|
||||
|
||||
// Get the backend
|
||||
b := backend.TestBackendConfig(t, New(), backend.TestWrapConfig(map[string]interface{}{
|
||||
b := backend.TestBackendConfig(t, New(encryption.StateEncryptionDisabled()), backend.TestWrapConfig(map[string]interface{}{
|
||||
"address": srv.HTTPAddr,
|
||||
"path": statePath,
|
||||
}))
|
||||
@ -80,7 +81,7 @@ func TestRemoteClient_gzipUpgrade(t *testing.T) {
|
||||
remote.TestClient(t, state.(*remote.State).Client)
|
||||
|
||||
// create a new backend with gzip
|
||||
b = backend.TestBackendConfig(t, New(), backend.TestWrapConfig(map[string]interface{}{
|
||||
b = backend.TestBackendConfig(t, New(encryption.StateEncryptionDisabled()), backend.TestWrapConfig(map[string]interface{}{
|
||||
"address": srv.HTTPAddr,
|
||||
"path": statePath,
|
||||
"gzip": true,
|
||||
@ -105,7 +106,7 @@ func TestConsul_largeState(t *testing.T) {
|
||||
|
||||
path := "tf-unit/test-large-state"
|
||||
|
||||
b := backend.TestBackendConfig(t, New(), backend.TestWrapConfig(map[string]interface{}{
|
||||
b := backend.TestBackendConfig(t, New(encryption.StateEncryptionDisabled()), backend.TestWrapConfig(map[string]interface{}{
|
||||
"address": srv.HTTPAddr,
|
||||
"path": path,
|
||||
}))
|
||||
@ -191,7 +192,7 @@ func TestConsul_largeState(t *testing.T) {
|
||||
)
|
||||
|
||||
// Test with gzip and chunks
|
||||
b = backend.TestBackendConfig(t, New(), backend.TestWrapConfig(map[string]interface{}{
|
||||
b = backend.TestBackendConfig(t, New(encryption.StateEncryptionDisabled()), backend.TestWrapConfig(map[string]interface{}{
|
||||
"address": srv.HTTPAddr,
|
||||
"path": path,
|
||||
"gzip": true,
|
||||
@ -253,7 +254,7 @@ func TestConsul_stateLock(t *testing.T) {
|
||||
for _, path := range testCases {
|
||||
t.Run(path, func(*testing.T) {
|
||||
// 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(encryption.StateEncryptionDisabled()), backend.TestWrapConfig(map[string]interface{}{
|
||||
"address": srv.HTTPAddr,
|
||||
"path": path,
|
||||
})).StateMgr(backend.DefaultStateName)
|
||||
@ -261,7 +262,7 @@ func TestConsul_stateLock(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
sB, err := backend.TestBackendConfig(t, New(), backend.TestWrapConfig(map[string]interface{}{
|
||||
sB, err := backend.TestBackendConfig(t, New(encryption.StateEncryptionDisabled()), backend.TestWrapConfig(map[string]interface{}{
|
||||
"address": srv.HTTPAddr,
|
||||
"path": path,
|
||||
})).StateMgr(backend.DefaultStateName)
|
||||
@ -297,7 +298,7 @@ func TestConsul_destroyLock(t *testing.T) {
|
||||
for _, path := range testCases {
|
||||
t.Run(path, func(*testing.T) {
|
||||
// Get the backend
|
||||
b := backend.TestBackendConfig(t, New(), backend.TestWrapConfig(map[string]interface{}{
|
||||
b := backend.TestBackendConfig(t, New(encryption.StateEncryptionDisabled()), backend.TestWrapConfig(map[string]interface{}{
|
||||
"address": srv.HTTPAddr,
|
||||
"path": path,
|
||||
}))
|
||||
@ -364,7 +365,7 @@ func TestConsul_lostLock(t *testing.T) {
|
||||
path := fmt.Sprintf("tf-unit/%s", time.Now().String())
|
||||
|
||||
// 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(encryption.StateEncryptionDisabled()), backend.TestWrapConfig(map[string]interface{}{
|
||||
"address": srv.HTTPAddr,
|
||||
"path": path,
|
||||
})).StateMgr(backend.DefaultStateName)
|
||||
@ -372,7 +373,7 @@ func TestConsul_lostLock(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
sB, err := backend.TestBackendConfig(t, New(), backend.TestWrapConfig(map[string]interface{}{
|
||||
sB, err := backend.TestBackendConfig(t, New(encryption.StateEncryptionDisabled()), backend.TestWrapConfig(map[string]interface{}{
|
||||
"address": srv.HTTPAddr,
|
||||
"path": path + "-not-used",
|
||||
})).StateMgr(backend.DefaultStateName)
|
||||
@ -422,7 +423,7 @@ func TestConsul_lostLockConnection(t *testing.T) {
|
||||
|
||||
path := fmt.Sprintf("tf-unit/%s", time.Now().String())
|
||||
|
||||
b := backend.TestBackendConfig(t, New(), backend.TestWrapConfig(map[string]interface{}{
|
||||
b := backend.TestBackendConfig(t, New(encryption.StateEncryptionDisabled()), backend.TestWrapConfig(map[string]interface{}{
|
||||
"address": srv.HTTPAddr,
|
||||
"path": path,
|
||||
}))
|
||||
|
@ -16,6 +16,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/opentofu/opentofu/internal/backend"
|
||||
"github.com/opentofu/opentofu/internal/encryption"
|
||||
"github.com/opentofu/opentofu/internal/legacy/helper/schema"
|
||||
"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common"
|
||||
"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/profile"
|
||||
@ -38,6 +39,7 @@ const (
|
||||
// Backend implements "backend".Backend for tencentCloud cos
|
||||
type Backend struct {
|
||||
*schema.Backend
|
||||
encryption encryption.StateEncryption
|
||||
credential *common.Credential
|
||||
|
||||
cosContext context.Context
|
||||
@ -54,7 +56,7 @@ type Backend struct {
|
||||
}
|
||||
|
||||
// New creates a new backend for TencentCloud cos remote state.
|
||||
func New() backend.Backend {
|
||||
func New(enc encryption.StateEncryption) backend.Backend {
|
||||
s := &schema.Backend{
|
||||
Schema: map[string]*schema.Schema{
|
||||
"secret_id": {
|
||||
@ -182,7 +184,7 @@ func New() backend.Backend {
|
||||
},
|
||||
}
|
||||
|
||||
result := &Backend{Backend: s}
|
||||
result := &Backend{Backend: s, encryption: enc}
|
||||
result.Backend.ConfigureFunc = result.configure
|
||||
|
||||
return result
|
||||
|
@ -85,7 +85,7 @@ func (b *Backend) StateMgr(name string) (statemgr.Full, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
stateMgr := &remote.State{Client: c}
|
||||
stateMgr := remote.NewState(c, b.encryption)
|
||||
|
||||
ws, err := b.Workspaces()
|
||||
if err != nil {
|
||||
|
@ -13,6 +13,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/opentofu/opentofu/internal/backend"
|
||||
"github.com/opentofu/opentofu/internal/encryption"
|
||||
"github.com/opentofu/opentofu/internal/states/remote"
|
||||
)
|
||||
|
||||
@ -225,7 +226,7 @@ func setupBackend(t *testing.T, bucket, prefix, key string, encrypt bool) backen
|
||||
"key": key,
|
||||
}
|
||||
|
||||
b := backend.TestBackendConfig(t, New(), backend.TestWrapConfig(config))
|
||||
b := backend.TestBackendConfig(t, New(encryption.StateEncryptionDisabled()), backend.TestWrapConfig(config))
|
||||
be := b.(*Backend)
|
||||
|
||||
c, err := be.client("tencentcloud")
|
||||
|
@ -16,6 +16,7 @@ import (
|
||||
|
||||
"cloud.google.com/go/storage"
|
||||
"github.com/opentofu/opentofu/internal/backend"
|
||||
"github.com/opentofu/opentofu/internal/encryption"
|
||||
"github.com/opentofu/opentofu/internal/httpclient"
|
||||
"github.com/opentofu/opentofu/internal/legacy/helper/schema"
|
||||
"github.com/opentofu/opentofu/version"
|
||||
@ -29,6 +30,7 @@ import (
|
||||
// State(), DeleteState() and States() are implemented explicitly.
|
||||
type Backend struct {
|
||||
*schema.Backend
|
||||
encryption encryption.StateEncryption
|
||||
|
||||
storageClient *storage.Client
|
||||
storageContext context.Context
|
||||
@ -40,8 +42,8 @@ type Backend struct {
|
||||
kmsKeyName string
|
||||
}
|
||||
|
||||
func New() backend.Backend {
|
||||
b := &Backend{}
|
||||
func New(enc encryption.StateEncryption) backend.Backend {
|
||||
b := &Backend{encryption: enc}
|
||||
b.Backend = &schema.Backend{
|
||||
ConfigureFunc: b.configure,
|
||||
Schema: map[string]*schema.Schema{
|
||||
|
@ -98,7 +98,7 @@ func (b *Backend) StateMgr(name string) (statemgr.Full, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
st := &remote.State{Client: c}
|
||||
st := remote.NewState(c, b.encryption)
|
||||
|
||||
// Grab the value
|
||||
if err := st.RefreshState(); err != nil {
|
||||
|
@ -18,6 +18,7 @@ import (
|
||||
kms "cloud.google.com/go/kms/apiv1"
|
||||
"cloud.google.com/go/storage"
|
||||
"github.com/opentofu/opentofu/internal/backend"
|
||||
"github.com/opentofu/opentofu/internal/encryption"
|
||||
"github.com/opentofu/opentofu/internal/httpclient"
|
||||
"github.com/opentofu/opentofu/internal/states/remote"
|
||||
"github.com/opentofu/opentofu/version"
|
||||
@ -238,7 +239,7 @@ func setupBackend(t *testing.T, bucket, prefix, key, kmsName string) backend.Bac
|
||||
config["kms_encryption_key"] = kmsName
|
||||
}
|
||||
|
||||
b := backend.TestBackendConfig(t, New(), backend.TestWrapConfig(config))
|
||||
b := backend.TestBackendConfig(t, New(encryption.StateEncryptionDisabled()), backend.TestWrapConfig(config))
|
||||
be := b.(*Backend)
|
||||
|
||||
// create the bucket if it doesn't exist
|
||||
|
@ -19,13 +19,14 @@ import (
|
||||
"github.com/hashicorp/go-retryablehttp"
|
||||
|
||||
"github.com/opentofu/opentofu/internal/backend"
|
||||
"github.com/opentofu/opentofu/internal/encryption"
|
||||
"github.com/opentofu/opentofu/internal/legacy/helper/schema"
|
||||
"github.com/opentofu/opentofu/internal/logging"
|
||||
"github.com/opentofu/opentofu/internal/states/remote"
|
||||
"github.com/opentofu/opentofu/internal/states/statemgr"
|
||||
)
|
||||
|
||||
func New() backend.Backend {
|
||||
func New(enc encryption.StateEncryption) backend.Backend {
|
||||
s := &schema.Backend{
|
||||
Schema: map[string]*schema.Schema{
|
||||
"address": &schema.Schema{
|
||||
@ -121,13 +122,14 @@ func New() backend.Backend {
|
||||
},
|
||||
}
|
||||
|
||||
b := &Backend{Backend: s}
|
||||
b := &Backend{Backend: s, encryption: enc}
|
||||
b.Backend.ConfigureFunc = b.configure
|
||||
return b
|
||||
}
|
||||
|
||||
type Backend struct {
|
||||
*schema.Backend
|
||||
encryption encryption.StateEncryption
|
||||
|
||||
client *httpClient
|
||||
}
|
||||
@ -250,7 +252,7 @@ func (b *Backend) StateMgr(name string) (statemgr.Full, error) {
|
||||
return nil, backend.ErrWorkspacesNotSupported
|
||||
}
|
||||
|
||||
return &remote.State{Client: b.client}, nil
|
||||
return remote.NewState(b.client, b.encryption), nil
|
||||
}
|
||||
|
||||
func (b *Backend) Workspaces() ([]string, error) {
|
||||
|
@ -10,6 +10,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/opentofu/opentofu/internal/configs"
|
||||
"github.com/opentofu/opentofu/internal/encryption"
|
||||
"github.com/zclconf/go-cty/cty"
|
||||
|
||||
"github.com/opentofu/opentofu/internal/backend"
|
||||
@ -25,7 +26,7 @@ func TestHTTPClientFactory(t *testing.T) {
|
||||
conf := map[string]cty.Value{
|
||||
"address": cty.StringVal("http://127.0.0.1:8888/foo"),
|
||||
}
|
||||
b := backend.TestBackendConfig(t, New(), configs.SynthBody("synth", conf)).(*Backend)
|
||||
b := backend.TestBackendConfig(t, New(encryption.StateEncryptionDisabled()), configs.SynthBody("synth", conf)).(*Backend)
|
||||
client := b.client
|
||||
|
||||
if client == nil {
|
||||
@ -62,7 +63,7 @@ func TestHTTPClientFactory(t *testing.T) {
|
||||
"retry_wait_max": cty.StringVal("150"),
|
||||
}
|
||||
|
||||
b = backend.TestBackendConfig(t, New(), configs.SynthBody("synth", conf)).(*Backend)
|
||||
b = backend.TestBackendConfig(t, New(encryption.StateEncryptionDisabled()), configs.SynthBody("synth", conf)).(*Backend)
|
||||
client = b.client
|
||||
|
||||
if client == nil {
|
||||
@ -122,7 +123,7 @@ func TestHTTPClientFactoryWithEnv(t *testing.T) {
|
||||
t.Setenv("TF_HTTP_RETRY_WAIT_MIN", conf["retry_wait_min"])
|
||||
t.Setenv("TF_HTTP_RETRY_WAIT_MAX", conf["retry_wait_max"])
|
||||
|
||||
b := backend.TestBackendConfig(t, New(), nil).(*Backend)
|
||||
b := backend.TestBackendConfig(t, New(encryption.StateEncryptionDisabled()), nil).(*Backend)
|
||||
client := b.client
|
||||
|
||||
if client == nil {
|
||||
|
@ -31,6 +31,7 @@ import (
|
||||
"github.com/opentofu/opentofu/internal/addrs"
|
||||
"github.com/opentofu/opentofu/internal/backend"
|
||||
"github.com/opentofu/opentofu/internal/configs"
|
||||
"github.com/opentofu/opentofu/internal/encryption"
|
||||
"github.com/opentofu/opentofu/internal/states"
|
||||
"github.com/zclconf/go-cty/cty"
|
||||
)
|
||||
@ -276,7 +277,7 @@ func TestMTLSServer_NoCertFails(t *testing.T) {
|
||||
"address": cty.StringVal(url),
|
||||
"skip_cert_verification": cty.BoolVal(true),
|
||||
}
|
||||
b := backend.TestBackendConfig(t, New(), configs.SynthBody("synth", conf)).(*Backend)
|
||||
b := backend.TestBackendConfig(t, New(encryption.StateEncryptionDisabled()), configs.SynthBody("synth", conf)).(*Backend)
|
||||
if nil == b {
|
||||
t.Fatal("nil backend")
|
||||
}
|
||||
@ -347,7 +348,7 @@ func TestMTLSServer_WithCertPasses(t *testing.T) {
|
||||
"client_certificate_pem": cty.StringVal(string(clientCertData)),
|
||||
"client_private_key_pem": cty.StringVal(string(clientKeyData)),
|
||||
}
|
||||
b := backend.TestBackendConfig(t, New(), configs.SynthBody("synth", conf)).(*Backend)
|
||||
b := backend.TestBackendConfig(t, New(encryption.StateEncryptionDisabled()), configs.SynthBody("synth", conf)).(*Backend)
|
||||
if nil == b {
|
||||
t.Fatal("nil backend")
|
||||
}
|
||||
|
@ -14,6 +14,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/opentofu/opentofu/internal/backend"
|
||||
"github.com/opentofu/opentofu/internal/encryption"
|
||||
"github.com/opentofu/opentofu/internal/legacy/helper/schema"
|
||||
statespkg "github.com/opentofu/opentofu/internal/states"
|
||||
"github.com/opentofu/opentofu/internal/states/remote"
|
||||
@ -46,7 +47,7 @@ func Reset() {
|
||||
}
|
||||
|
||||
// New creates a new backend for Inmem remote state.
|
||||
func New() backend.Backend {
|
||||
func New(enc encryption.StateEncryption) backend.Backend {
|
||||
// Set the schema
|
||||
s := &schema.Backend{
|
||||
Schema: map[string]*schema.Schema{
|
||||
@ -57,13 +58,14 @@ func New() backend.Backend {
|
||||
},
|
||||
},
|
||||
}
|
||||
backend := &Backend{Backend: s}
|
||||
backend := &Backend{Backend: s, encryption: enc}
|
||||
backend.Backend.ConfigureFunc = backend.configure
|
||||
return backend
|
||||
}
|
||||
|
||||
type Backend struct {
|
||||
*schema.Backend
|
||||
encryption encryption.StateEncryption
|
||||
}
|
||||
|
||||
func (b *Backend) configure(ctx context.Context) error {
|
||||
@ -124,11 +126,12 @@ func (b *Backend) StateMgr(name string) (statemgr.Full, error) {
|
||||
|
||||
s := states.m[name]
|
||||
if s == nil {
|
||||
s = &remote.State{
|
||||
Client: &RemoteClient{
|
||||
s = remote.NewState(
|
||||
&RemoteClient{
|
||||
Name: name,
|
||||
},
|
||||
}
|
||||
b.encryption,
|
||||
)
|
||||
states.m[name] = s
|
||||
|
||||
// to most closely replicate other implementations, we are going to
|
||||
|
@ -13,6 +13,7 @@ import (
|
||||
"github.com/hashicorp/hcl/v2"
|
||||
|
||||
"github.com/opentofu/opentofu/internal/backend"
|
||||
"github.com/opentofu/opentofu/internal/encryption"
|
||||
statespkg "github.com/opentofu/opentofu/internal/states"
|
||||
"github.com/opentofu/opentofu/internal/states/remote"
|
||||
|
||||
@ -36,7 +37,7 @@ func TestBackendConfig(t *testing.T) {
|
||||
"lock_id": testID,
|
||||
}
|
||||
|
||||
b := backend.TestBackendConfig(t, New(), backend.TestWrapConfig(config)).(*Backend)
|
||||
b := backend.TestBackendConfig(t, New(encryption.StateEncryptionDisabled()), backend.TestWrapConfig(config)).(*Backend)
|
||||
|
||||
s, err := b.StateMgr(backend.DefaultStateName)
|
||||
if err != nil {
|
||||
@ -55,14 +56,14 @@ func TestBackendConfig(t *testing.T) {
|
||||
|
||||
func TestBackend(t *testing.T) {
|
||||
defer Reset()
|
||||
b := backend.TestBackendConfig(t, New(), hcl.EmptyBody()).(*Backend)
|
||||
b := backend.TestBackendConfig(t, New(encryption.StateEncryptionDisabled()), hcl.EmptyBody()).(*Backend)
|
||||
backend.TestBackendStates(t, b)
|
||||
}
|
||||
|
||||
func TestBackendLocked(t *testing.T) {
|
||||
defer Reset()
|
||||
b1 := backend.TestBackendConfig(t, New(), hcl.EmptyBody()).(*Backend)
|
||||
b2 := backend.TestBackendConfig(t, New(), hcl.EmptyBody()).(*Backend)
|
||||
b1 := backend.TestBackendConfig(t, New(encryption.StateEncryptionDisabled()), hcl.EmptyBody()).(*Backend)
|
||||
b2 := backend.TestBackendConfig(t, New(encryption.StateEncryptionDisabled()), hcl.EmptyBody()).(*Backend)
|
||||
|
||||
backend.TestBackendStateLocks(t, b1, b2)
|
||||
}
|
||||
@ -70,7 +71,7 @@ func TestBackendLocked(t *testing.T) {
|
||||
// use the this backen to test the remote.State implementation
|
||||
func TestRemoteState(t *testing.T) {
|
||||
defer Reset()
|
||||
b := backend.TestBackendConfig(t, New(), hcl.EmptyBody())
|
||||
b := backend.TestBackendConfig(t, New(encryption.StateEncryptionDisabled()), hcl.EmptyBody())
|
||||
|
||||
workspace := "workspace"
|
||||
|
||||
|
@ -10,6 +10,7 @@ import (
|
||||
|
||||
"github.com/hashicorp/hcl/v2"
|
||||
"github.com/opentofu/opentofu/internal/backend"
|
||||
"github.com/opentofu/opentofu/internal/encryption"
|
||||
"github.com/opentofu/opentofu/internal/states/remote"
|
||||
)
|
||||
|
||||
@ -20,7 +21,7 @@ func TestRemoteClient_impl(t *testing.T) {
|
||||
|
||||
func TestRemoteClient(t *testing.T) {
|
||||
defer Reset()
|
||||
b := backend.TestBackendConfig(t, New(), hcl.EmptyBody())
|
||||
b := backend.TestBackendConfig(t, New(encryption.StateEncryptionDisabled()), hcl.EmptyBody())
|
||||
|
||||
s, err := b.StateMgr(backend.DefaultStateName)
|
||||
if err != nil {
|
||||
@ -32,7 +33,7 @@ func TestRemoteClient(t *testing.T) {
|
||||
|
||||
func TestInmemLocks(t *testing.T) {
|
||||
defer Reset()
|
||||
s, err := backend.TestBackendConfig(t, New(), hcl.EmptyBody()).StateMgr(backend.DefaultStateName)
|
||||
s, err := backend.TestBackendConfig(t, New(encryption.StateEncryptionDisabled()), hcl.EmptyBody()).StateMgr(backend.DefaultStateName)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -15,6 +15,7 @@ import (
|
||||
|
||||
"github.com/mitchellh/go-homedir"
|
||||
"github.com/opentofu/opentofu/internal/backend"
|
||||
"github.com/opentofu/opentofu/internal/encryption"
|
||||
"github.com/opentofu/opentofu/internal/httpclient"
|
||||
"github.com/opentofu/opentofu/internal/legacy/helper/schema"
|
||||
"github.com/opentofu/opentofu/version"
|
||||
@ -36,7 +37,7 @@ var (
|
||||
)
|
||||
|
||||
// New creates a new backend for kubernetes remote state.
|
||||
func New() backend.Backend {
|
||||
func New(enc encryption.StateEncryption) backend.Backend {
|
||||
s := &schema.Backend{
|
||||
Schema: map[string]*schema.Schema{
|
||||
"secret_suffix": {
|
||||
@ -176,13 +177,14 @@ func New() backend.Backend {
|
||||
},
|
||||
}
|
||||
|
||||
result := &Backend{Backend: s}
|
||||
result := &Backend{Backend: s, encryption: enc}
|
||||
result.Backend.ConfigureFunc = result.configure
|
||||
return result
|
||||
}
|
||||
|
||||
type Backend struct {
|
||||
*schema.Backend
|
||||
encryption encryption.StateEncryption
|
||||
|
||||
// The fields below are set from configure
|
||||
kubernetesSecretClient dynamic.ResourceInterface
|
||||
|
@ -84,7 +84,7 @@ func (b *Backend) StateMgr(name string) (statemgr.Full, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
stateMgr := &remote.State{Client: c}
|
||||
stateMgr := remote.NewState(c, b.encryption)
|
||||
|
||||
// Grab the value
|
||||
if err := stateMgr.RefreshState(); err != nil {
|
||||
|
@ -15,6 +15,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/opentofu/opentofu/internal/backend"
|
||||
"github.com/opentofu/opentofu/internal/encryption"
|
||||
"github.com/opentofu/opentofu/internal/states/statemgr"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
@ -52,7 +53,7 @@ func TestBackend(t *testing.T) {
|
||||
testACC(t)
|
||||
defer cleanupK8sResources(t)
|
||||
|
||||
b1 := backend.TestBackendConfig(t, New(), backend.TestWrapConfig(map[string]interface{}{
|
||||
b1 := backend.TestBackendConfig(t, New(encryption.StateEncryptionDisabled()), backend.TestWrapConfig(map[string]interface{}{
|
||||
"secret_suffix": secretSuffix,
|
||||
}))
|
||||
|
||||
@ -65,11 +66,11 @@ func TestBackendLocks(t *testing.T) {
|
||||
defer cleanupK8sResources(t)
|
||||
|
||||
// Get the backend. We need two to test locking.
|
||||
b1 := backend.TestBackendConfig(t, New(), backend.TestWrapConfig(map[string]interface{}{
|
||||
b1 := backend.TestBackendConfig(t, New(encryption.StateEncryptionDisabled()), backend.TestWrapConfig(map[string]interface{}{
|
||||
"secret_suffix": secretSuffix,
|
||||
}))
|
||||
|
||||
b2 := backend.TestBackendConfig(t, New(), backend.TestWrapConfig(map[string]interface{}{
|
||||
b2 := backend.TestBackendConfig(t, New(encryption.StateEncryptionDisabled()), backend.TestWrapConfig(map[string]interface{}{
|
||||
"secret_suffix": secretSuffix,
|
||||
}))
|
||||
|
||||
@ -87,7 +88,7 @@ func TestBackendLocksSoak(t *testing.T) {
|
||||
|
||||
lockers := []statemgr.Locker{}
|
||||
for i := 0; i < clientCount; i++ {
|
||||
b := backend.TestBackendConfig(t, New(), backend.TestWrapConfig(map[string]interface{}{
|
||||
b := backend.TestBackendConfig(t, New(encryption.StateEncryptionDisabled()), backend.TestWrapConfig(map[string]interface{}{
|
||||
"secret_suffix": secretSuffix,
|
||||
}))
|
||||
|
||||
@ -132,7 +133,7 @@ func TestBackendLocksSoak(t *testing.T) {
|
||||
func cleanupK8sResources(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
// Get a backend to use the k8s client
|
||||
b1 := backend.TestBackendConfig(t, New(), backend.TestWrapConfig(map[string]interface{}{
|
||||
b1 := backend.TestBackendConfig(t, New(encryption.StateEncryptionDisabled()), backend.TestWrapConfig(map[string]interface{}{
|
||||
"secret_suffix": secretSuffix,
|
||||
}))
|
||||
|
||||
|
@ -9,6 +9,7 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/opentofu/opentofu/internal/backend"
|
||||
"github.com/opentofu/opentofu/internal/encryption"
|
||||
"github.com/opentofu/opentofu/internal/states/remote"
|
||||
"github.com/opentofu/opentofu/internal/states/statemgr"
|
||||
)
|
||||
@ -22,7 +23,7 @@ func TestRemoteClient(t *testing.T) {
|
||||
testACC(t)
|
||||
defer cleanupK8sResources(t)
|
||||
|
||||
b := backend.TestBackendConfig(t, New(), backend.TestWrapConfig(map[string]interface{}{
|
||||
b := backend.TestBackendConfig(t, New(encryption.StateEncryptionDisabled()), backend.TestWrapConfig(map[string]interface{}{
|
||||
"secret_suffix": secretSuffix,
|
||||
}))
|
||||
|
||||
@ -38,11 +39,11 @@ func TestRemoteClientLocks(t *testing.T) {
|
||||
testACC(t)
|
||||
defer cleanupK8sResources(t)
|
||||
|
||||
b1 := backend.TestBackendConfig(t, New(), backend.TestWrapConfig(map[string]interface{}{
|
||||
b1 := backend.TestBackendConfig(t, New(encryption.StateEncryptionDisabled()), backend.TestWrapConfig(map[string]interface{}{
|
||||
"secret_suffix": secretSuffix,
|
||||
}))
|
||||
|
||||
b2 := backend.TestBackendConfig(t, New(), backend.TestWrapConfig(map[string]interface{}{
|
||||
b2 := backend.TestBackendConfig(t, New(encryption.StateEncryptionDisabled()), backend.TestWrapConfig(map[string]interface{}{
|
||||
"secret_suffix": secretSuffix,
|
||||
}))
|
||||
|
||||
@ -63,11 +64,11 @@ func TestForceUnlock(t *testing.T) {
|
||||
testACC(t)
|
||||
defer cleanupK8sResources(t)
|
||||
|
||||
b1 := backend.TestBackendConfig(t, New(), backend.TestWrapConfig(map[string]interface{}{
|
||||
b1 := backend.TestBackendConfig(t, New(encryption.StateEncryptionDisabled()), backend.TestWrapConfig(map[string]interface{}{
|
||||
"secret_suffix": secretSuffix,
|
||||
}))
|
||||
|
||||
b2 := backend.TestBackendConfig(t, New(), backend.TestWrapConfig(map[string]interface{}{
|
||||
b2 := backend.TestBackendConfig(t, New(encryption.StateEncryptionDisabled()), backend.TestWrapConfig(map[string]interface{}{
|
||||
"secret_suffix": secretSuffix,
|
||||
}))
|
||||
|
||||
|
@ -34,6 +34,7 @@ import (
|
||||
"github.com/mitchellh/go-homedir"
|
||||
|
||||
"github.com/opentofu/opentofu/internal/backend"
|
||||
"github.com/opentofu/opentofu/internal/encryption"
|
||||
"github.com/opentofu/opentofu/internal/httpclient"
|
||||
"github.com/opentofu/opentofu/internal/legacy/helper/schema"
|
||||
"github.com/opentofu/opentofu/version"
|
||||
@ -90,7 +91,7 @@ func deprecatedAssumeRoleSchema() *schema.Schema {
|
||||
}
|
||||
|
||||
// New creates a new backend for OSS remote state.
|
||||
func New() backend.Backend {
|
||||
func New(enc encryption.StateEncryption) backend.Backend {
|
||||
s := &schema.Backend{
|
||||
Schema: map[string]*schema.Schema{
|
||||
"access_key": {
|
||||
@ -262,13 +263,14 @@ func New() backend.Backend {
|
||||
},
|
||||
}
|
||||
|
||||
result := &Backend{Backend: s}
|
||||
result := &Backend{Backend: s, encryption: enc}
|
||||
result.Backend.ConfigureFunc = result.configure
|
||||
return result
|
||||
}
|
||||
|
||||
type Backend struct {
|
||||
*schema.Backend
|
||||
encryption encryption.StateEncryption
|
||||
|
||||
// The fields below are set from configure
|
||||
ossClient *oss.Client
|
||||
|
@ -118,7 +118,7 @@ func (b *Backend) StateMgr(name string) (statemgr.Full, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
stateMgr := &remote.State{Client: client}
|
||||
stateMgr := remote.NewState(client, b.encryption)
|
||||
|
||||
// Check to see if this state already exists.
|
||||
existing, err := b.Workspaces()
|
||||
|
@ -18,6 +18,7 @@ import (
|
||||
"github.com/aliyun/aliyun-tablestore-go-sdk/tablestore"
|
||||
"github.com/opentofu/opentofu/internal/backend"
|
||||
"github.com/opentofu/opentofu/internal/configs/hcl2shim"
|
||||
"github.com/opentofu/opentofu/internal/encryption"
|
||||
)
|
||||
|
||||
// verify that we are doing ACC tests or the OSS tests specifically
|
||||
@ -49,7 +50,7 @@ func TestBackendConfig(t *testing.T) {
|
||||
"tablestore_table": "TableStore",
|
||||
}
|
||||
|
||||
b := backend.TestBackendConfig(t, New(), backend.TestWrapConfig(config)).(*Backend)
|
||||
b := backend.TestBackendConfig(t, New(encryption.StateEncryptionDisabled()), backend.TestWrapConfig(config)).(*Backend)
|
||||
|
||||
if !strings.HasPrefix(b.ossClient.Config.Endpoint, "https://oss-cn-beijing") {
|
||||
t.Fatalf("Incorrect region was provided")
|
||||
@ -84,7 +85,7 @@ func TestBackendConfigWorkSpace(t *testing.T) {
|
||||
"tablestore_table": "TableStore",
|
||||
}
|
||||
|
||||
b := backend.TestBackendConfig(t, New(), backend.TestWrapConfig(config)).(*Backend)
|
||||
b := backend.TestBackendConfig(t, New(encryption.StateEncryptionDisabled()), backend.TestWrapConfig(config)).(*Backend)
|
||||
createOSSBucket(t, b.ossClient, bucketName)
|
||||
defer deleteOSSBucket(t, b.ossClient, bucketName)
|
||||
if _, err := b.Workspaces(); err != nil {
|
||||
@ -123,7 +124,7 @@ func TestBackendConfigProfile(t *testing.T) {
|
||||
"profile": "default",
|
||||
}
|
||||
|
||||
b := backend.TestBackendConfig(t, New(), backend.TestWrapConfig(config)).(*Backend)
|
||||
b := backend.TestBackendConfig(t, New(encryption.StateEncryptionDisabled()), backend.TestWrapConfig(config)).(*Backend)
|
||||
|
||||
if !strings.HasPrefix(b.ossClient.Config.Endpoint, "https://oss-cn-beijing") {
|
||||
t.Fatalf("Incorrect region was provided")
|
||||
@ -157,7 +158,7 @@ func TestBackendConfig_invalidKey(t *testing.T) {
|
||||
"tablestore_table": "TableStore",
|
||||
})
|
||||
|
||||
_, results := New().PrepareConfig(cfg)
|
||||
_, results := New(encryption.StateEncryptionDisabled()).PrepareConfig(cfg)
|
||||
if !results.HasErrors() {
|
||||
t.Fatal("expected config validation error")
|
||||
}
|
||||
@ -169,12 +170,12 @@ func TestBackend(t *testing.T) {
|
||||
bucketName := fmt.Sprintf("terraform-remote-oss-test-%x", time.Now().Unix())
|
||||
statePrefix := "multi/level/path/"
|
||||
|
||||
b1 := backend.TestBackendConfig(t, New(), backend.TestWrapConfig(map[string]interface{}{
|
||||
b1 := backend.TestBackendConfig(t, New(encryption.StateEncryptionDisabled()), backend.TestWrapConfig(map[string]interface{}{
|
||||
"bucket": bucketName,
|
||||
"prefix": statePrefix,
|
||||
})).(*Backend)
|
||||
|
||||
b2 := backend.TestBackendConfig(t, New(), backend.TestWrapConfig(map[string]interface{}{
|
||||
b2 := backend.TestBackendConfig(t, New(encryption.StateEncryptionDisabled()), backend.TestWrapConfig(map[string]interface{}{
|
||||
"bucket": bucketName,
|
||||
"prefix": statePrefix,
|
||||
})).(*Backend)
|
||||
|
@ -15,6 +15,7 @@ import (
|
||||
"crypto/md5"
|
||||
|
||||
"github.com/opentofu/opentofu/internal/backend"
|
||||
"github.com/opentofu/opentofu/internal/encryption"
|
||||
"github.com/opentofu/opentofu/internal/states/remote"
|
||||
"github.com/opentofu/opentofu/internal/states/statefile"
|
||||
"github.com/opentofu/opentofu/internal/states/statemgr"
|
||||
@ -33,7 +34,7 @@ func TestRemoteClient(t *testing.T) {
|
||||
bucketName := fmt.Sprintf("tf-remote-oss-test-%x", time.Now().Unix())
|
||||
path := "testState"
|
||||
|
||||
b := backend.TestBackendConfig(t, New(), backend.TestWrapConfig(map[string]interface{}{
|
||||
b := backend.TestBackendConfig(t, New(encryption.StateEncryptionDisabled()), backend.TestWrapConfig(map[string]interface{}{
|
||||
"bucket": bucketName,
|
||||
"prefix": path,
|
||||
"encrypt": true,
|
||||
@ -56,7 +57,7 @@ func TestRemoteClientLocks(t *testing.T) {
|
||||
tableName := fmt.Sprintf("tfRemoteTestForce%x", time.Now().Unix())
|
||||
path := "testState"
|
||||
|
||||
b1 := backend.TestBackendConfig(t, New(), backend.TestWrapConfig(map[string]interface{}{
|
||||
b1 := backend.TestBackendConfig(t, New(encryption.StateEncryptionDisabled()), backend.TestWrapConfig(map[string]interface{}{
|
||||
"bucket": bucketName,
|
||||
"prefix": path,
|
||||
"encrypt": true,
|
||||
@ -64,7 +65,7 @@ func TestRemoteClientLocks(t *testing.T) {
|
||||
"tablestore_endpoint": RemoteTestUsedOTSEndpoint,
|
||||
})).(*Backend)
|
||||
|
||||
b2 := backend.TestBackendConfig(t, New(), backend.TestWrapConfig(map[string]interface{}{
|
||||
b2 := backend.TestBackendConfig(t, New(encryption.StateEncryptionDisabled()), backend.TestWrapConfig(map[string]interface{}{
|
||||
"bucket": bucketName,
|
||||
"prefix": path,
|
||||
"encrypt": true,
|
||||
@ -97,7 +98,7 @@ func TestRemoteClientLocks_multipleStates(t *testing.T) {
|
||||
tableName := fmt.Sprintf("tfRemoteTestForce%x", time.Now().Unix())
|
||||
path := "testState"
|
||||
|
||||
b1 := backend.TestBackendConfig(t, New(), backend.TestWrapConfig(map[string]interface{}{
|
||||
b1 := backend.TestBackendConfig(t, New(encryption.StateEncryptionDisabled()), backend.TestWrapConfig(map[string]interface{}{
|
||||
"bucket": bucketName,
|
||||
"prefix": path,
|
||||
"encrypt": true,
|
||||
@ -105,7 +106,7 @@ func TestRemoteClientLocks_multipleStates(t *testing.T) {
|
||||
"tablestore_endpoint": RemoteTestUsedOTSEndpoint,
|
||||
})).(*Backend)
|
||||
|
||||
b2 := backend.TestBackendConfig(t, New(), backend.TestWrapConfig(map[string]interface{}{
|
||||
b2 := backend.TestBackendConfig(t, New(encryption.StateEncryptionDisabled()), backend.TestWrapConfig(map[string]interface{}{
|
||||
"bucket": bucketName,
|
||||
"prefix": path,
|
||||
"encrypt": true,
|
||||
@ -143,7 +144,7 @@ func TestRemoteForceUnlock(t *testing.T) {
|
||||
tableName := fmt.Sprintf("tfRemoteTestForce%x", time.Now().Unix())
|
||||
path := "testState"
|
||||
|
||||
b1 := backend.TestBackendConfig(t, New(), backend.TestWrapConfig(map[string]interface{}{
|
||||
b1 := backend.TestBackendConfig(t, New(encryption.StateEncryptionDisabled()), backend.TestWrapConfig(map[string]interface{}{
|
||||
"bucket": bucketName,
|
||||
"prefix": path,
|
||||
"encrypt": true,
|
||||
@ -151,7 +152,7 @@ func TestRemoteForceUnlock(t *testing.T) {
|
||||
"tablestore_endpoint": RemoteTestUsedOTSEndpoint,
|
||||
})).(*Backend)
|
||||
|
||||
b2 := backend.TestBackendConfig(t, New(), backend.TestWrapConfig(map[string]interface{}{
|
||||
b2 := backend.TestBackendConfig(t, New(encryption.StateEncryptionDisabled()), backend.TestWrapConfig(map[string]interface{}{
|
||||
"bucket": bucketName,
|
||||
"prefix": path,
|
||||
"encrypt": true,
|
||||
@ -223,7 +224,7 @@ func TestRemoteClient_clientMD5(t *testing.T) {
|
||||
tableName := fmt.Sprintf("tfRemoteTestForce%x", time.Now().Unix())
|
||||
path := "testState"
|
||||
|
||||
b := backend.TestBackendConfig(t, New(), backend.TestWrapConfig(map[string]interface{}{
|
||||
b := backend.TestBackendConfig(t, New(encryption.StateEncryptionDisabled()), backend.TestWrapConfig(map[string]interface{}{
|
||||
"bucket": bucketName,
|
||||
"prefix": path,
|
||||
"tablestore_table": tableName,
|
||||
@ -273,7 +274,7 @@ func TestRemoteClient_stateChecksum(t *testing.T) {
|
||||
tableName := fmt.Sprintf("tfRemoteTestForce%x", time.Now().Unix())
|
||||
path := "testState"
|
||||
|
||||
b1 := backend.TestBackendConfig(t, New(), backend.TestWrapConfig(map[string]interface{}{
|
||||
b1 := backend.TestBackendConfig(t, New(encryption.StateEncryptionDisabled()), backend.TestWrapConfig(map[string]interface{}{
|
||||
"bucket": bucketName,
|
||||
"prefix": path,
|
||||
"tablestore_table": tableName,
|
||||
@ -295,18 +296,18 @@ func TestRemoteClient_stateChecksum(t *testing.T) {
|
||||
s := statemgr.TestFullInitialState()
|
||||
sf := &statefile.File{State: s}
|
||||
var oldState bytes.Buffer
|
||||
if err := statefile.Write(sf, &oldState); err != nil {
|
||||
if err := statefile.Write(sf, &oldState, encryption.StateEncryptionDisabled()); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
sf.Serial++
|
||||
var newState bytes.Buffer
|
||||
if err := statefile.Write(sf, &newState); err != nil {
|
||||
if err := statefile.Write(sf, &newState, encryption.StateEncryptionDisabled()); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Use b2 without a tablestore_table to bypass the lock table to write the state directly.
|
||||
// client2 will write the "incorrect" state, simulating oss eventually consistency delays
|
||||
b2 := backend.TestBackendConfig(t, New(), backend.TestWrapConfig(map[string]interface{}{
|
||||
b2 := backend.TestBackendConfig(t, New(encryption.StateEncryptionDisabled()), backend.TestWrapConfig(map[string]interface{}{
|
||||
"bucket": bucketName,
|
||||
"prefix": path,
|
||||
})).(*Backend)
|
||||
|
@ -14,6 +14,7 @@ import (
|
||||
|
||||
"github.com/lib/pq"
|
||||
"github.com/opentofu/opentofu/internal/backend"
|
||||
"github.com/opentofu/opentofu/internal/encryption"
|
||||
"github.com/opentofu/opentofu/internal/legacy/helper/schema"
|
||||
)
|
||||
|
||||
@ -33,7 +34,7 @@ func defaultBoolFunc(k string, dv bool) schema.SchemaDefaultFunc {
|
||||
}
|
||||
|
||||
// New creates a new backend for Postgres remote state.
|
||||
func New() backend.Backend {
|
||||
func New(enc encryption.StateEncryption) backend.Backend {
|
||||
s := &schema.Backend{
|
||||
Schema: map[string]*schema.Schema{
|
||||
"conn_str": {
|
||||
@ -73,13 +74,14 @@ func New() backend.Backend {
|
||||
},
|
||||
}
|
||||
|
||||
result := &Backend{Backend: s}
|
||||
result := &Backend{Backend: s, encryption: enc}
|
||||
result.Backend.ConfigureFunc = result.configure
|
||||
return result
|
||||
}
|
||||
|
||||
type Backend struct {
|
||||
*schema.Backend
|
||||
encryption encryption.StateEncryption
|
||||
|
||||
// The fields below are set from configure
|
||||
db *sql.DB
|
||||
|
@ -56,13 +56,14 @@ func (b *Backend) DeleteWorkspace(name string, _ bool) error {
|
||||
|
||||
func (b *Backend) StateMgr(name string) (statemgr.Full, error) {
|
||||
// Build the state client
|
||||
var stateMgr statemgr.Full = &remote.State{
|
||||
Client: &RemoteClient{
|
||||
var stateMgr statemgr.Full = remote.NewState(
|
||||
&RemoteClient{
|
||||
Client: b.db,
|
||||
Name: name,
|
||||
SchemaName: b.schemaName,
|
||||
},
|
||||
}
|
||||
b.encryption,
|
||||
)
|
||||
|
||||
// Check to see if this state already exists.
|
||||
// If the state doesn't exist, we have to assume this
|
||||
|
@ -19,6 +19,7 @@ import (
|
||||
"github.com/hashicorp/hcl/v2/hcldec"
|
||||
"github.com/lib/pq"
|
||||
"github.com/opentofu/opentofu/internal/backend"
|
||||
"github.com/opentofu/opentofu/internal/encryption"
|
||||
"github.com/opentofu/opentofu/internal/states/remote"
|
||||
"github.com/opentofu/opentofu/internal/states/statemgr"
|
||||
"github.com/opentofu/opentofu/internal/tfdiags"
|
||||
@ -162,7 +163,7 @@ func TestBackendConfig(t *testing.T) {
|
||||
defer dbCleaner.Query(fmt.Sprintf("DROP SCHEMA IF EXISTS %s CASCADE", schemaName))
|
||||
|
||||
var diags tfdiags.Diagnostics
|
||||
b := New().(*Backend)
|
||||
b := New(encryption.StateEncryptionDisabled()).(*Backend)
|
||||
schema := b.ConfigSchema()
|
||||
spec := schema.DecoderSpec()
|
||||
obj, decDiags := hcldec.Decode(config, spec, nil)
|
||||
@ -325,7 +326,7 @@ func TestBackendConfigSkipOptions(t *testing.T) {
|
||||
}
|
||||
defer db.Query(fmt.Sprintf("DROP SCHEMA IF EXISTS %s CASCADE", schemaName))
|
||||
|
||||
b := backend.TestBackendConfig(t, New(), config).(*Backend)
|
||||
b := backend.TestBackendConfig(t, New(encryption.StateEncryptionDisabled()), config).(*Backend)
|
||||
|
||||
if b == nil {
|
||||
t.Fatal("Backend could not be configured")
|
||||
@ -398,7 +399,7 @@ func TestBackendStates(t *testing.T) {
|
||||
"conn_str": connStr,
|
||||
"schema_name": schemaName,
|
||||
})
|
||||
b := backend.TestBackendConfig(t, New(), config).(*Backend)
|
||||
b := backend.TestBackendConfig(t, New(encryption.StateEncryptionDisabled()), config).(*Backend)
|
||||
|
||||
if b == nil {
|
||||
t.Fatal("Backend could not be configured")
|
||||
@ -423,13 +424,13 @@ func TestBackendStateLocks(t *testing.T) {
|
||||
"conn_str": connStr,
|
||||
"schema_name": schemaName,
|
||||
})
|
||||
b := backend.TestBackendConfig(t, New(), config).(*Backend)
|
||||
b := backend.TestBackendConfig(t, New(encryption.StateEncryptionDisabled()), config).(*Backend)
|
||||
|
||||
if b == nil {
|
||||
t.Fatal("Backend could not be configured")
|
||||
}
|
||||
|
||||
bb := backend.TestBackendConfig(t, New(), config).(*Backend)
|
||||
bb := backend.TestBackendConfig(t, New(encryption.StateEncryptionDisabled()), config).(*Backend)
|
||||
|
||||
if bb == nil {
|
||||
t.Fatal("Backend could not be configured")
|
||||
@ -452,7 +453,7 @@ func TestBackendConcurrentLock(t *testing.T) {
|
||||
"conn_str": connStr,
|
||||
"schema_name": schemaName,
|
||||
})
|
||||
b := backend.TestBackendConfig(t, New(), config).(*Backend)
|
||||
b := backend.TestBackendConfig(t, New(encryption.StateEncryptionDisabled()), config).(*Backend)
|
||||
|
||||
if b == nil {
|
||||
t.Fatal("Backend could not be configured")
|
||||
|
@ -14,6 +14,7 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/opentofu/opentofu/internal/backend"
|
||||
"github.com/opentofu/opentofu/internal/encryption"
|
||||
"github.com/opentofu/opentofu/internal/states/remote"
|
||||
)
|
||||
|
||||
@ -36,7 +37,7 @@ func TestRemoteClient(t *testing.T) {
|
||||
"conn_str": connStr,
|
||||
"schema_name": schemaName,
|
||||
})
|
||||
b := backend.TestBackendConfig(t, New(), config).(*Backend)
|
||||
b := backend.TestBackendConfig(t, New(encryption.StateEncryptionDisabled()), config).(*Backend)
|
||||
|
||||
if b == nil {
|
||||
t.Fatal("Backend could not be configured")
|
||||
@ -65,13 +66,13 @@ func TestRemoteLocks(t *testing.T) {
|
||||
"schema_name": schemaName,
|
||||
})
|
||||
|
||||
b1 := backend.TestBackendConfig(t, New(), config).(*Backend)
|
||||
b1 := backend.TestBackendConfig(t, New(encryption.StateEncryptionDisabled()), config).(*Backend)
|
||||
s1, err := b1.StateMgr(backend.DefaultStateName)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
b2 := backend.TestBackendConfig(t, New(), config).(*Backend)
|
||||
b2 := backend.TestBackendConfig(t, New(encryption.StateEncryptionDisabled()), config).(*Backend)
|
||||
s2, err := b2.StateMgr(backend.DefaultStateName)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
|
@ -25,6 +25,7 @@ import (
|
||||
awsbaseValidation "github.com/hashicorp/aws-sdk-go-base/v2/validation"
|
||||
"github.com/opentofu/opentofu/internal/backend"
|
||||
"github.com/opentofu/opentofu/internal/configs/configschema"
|
||||
"github.com/opentofu/opentofu/internal/encryption"
|
||||
"github.com/opentofu/opentofu/internal/httpclient"
|
||||
"github.com/opentofu/opentofu/internal/logging"
|
||||
"github.com/opentofu/opentofu/internal/tfdiags"
|
||||
@ -33,14 +34,15 @@ import (
|
||||
"github.com/zclconf/go-cty/cty/gocty"
|
||||
)
|
||||
|
||||
func New() backend.Backend {
|
||||
return &Backend{}
|
||||
func New(enc encryption.StateEncryption) backend.Backend {
|
||||
return &Backend{encryption: enc}
|
||||
}
|
||||
|
||||
type Backend struct {
|
||||
s3Client *s3.Client
|
||||
dynClient *dynamodb.Client
|
||||
awsConfig aws.Config
|
||||
encryption encryption.StateEncryption
|
||||
s3Client *s3.Client
|
||||
dynClient *dynamodb.Client
|
||||
awsConfig aws.Config
|
||||
|
||||
bucketName string
|
||||
keyName string
|
||||
|
@ -19,6 +19,7 @@ import (
|
||||
"github.com/hashicorp/aws-sdk-go-base/v2/mockdata"
|
||||
"github.com/hashicorp/aws-sdk-go-base/v2/servicemocks"
|
||||
"github.com/opentofu/opentofu/internal/configs/hcl2shim"
|
||||
"github.com/opentofu/opentofu/internal/encryption"
|
||||
"github.com/opentofu/opentofu/internal/tfdiags"
|
||||
)
|
||||
|
||||
@ -2206,7 +2207,7 @@ func setSharedConfigFile(t *testing.T, filename string) {
|
||||
}
|
||||
|
||||
func configureBackend(t *testing.T, config map[string]any) (*Backend, tfdiags.Diagnostics) {
|
||||
b := New().(*Backend)
|
||||
b := New(encryption.StateEncryptionDisabled()).(*Backend)
|
||||
configSchema := populateSchema(t, b.ConfigSchema(), hcl2shim.HCL2ValueFromConfigValue(config))
|
||||
|
||||
configSchema, diags := b.PrepareConfig(configSchema)
|
||||
|
@ -148,7 +148,7 @@ func (b *Backend) StateMgr(name string) (statemgr.Full, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
stateMgr := &remote.State{Client: client}
|
||||
stateMgr := remote.NewState(client, b.encryption)
|
||||
// Check to see if this state already exists.
|
||||
// If we're trying to force-unlock a state, we can't take the lock before
|
||||
// fetching the state. If the state doesn't exist, we have to assume this
|
||||
|
@ -31,6 +31,7 @@ import (
|
||||
"github.com/opentofu/opentofu/internal/backend"
|
||||
"github.com/opentofu/opentofu/internal/configs/configschema"
|
||||
"github.com/opentofu/opentofu/internal/configs/hcl2shim"
|
||||
"github.com/opentofu/opentofu/internal/encryption"
|
||||
"github.com/opentofu/opentofu/internal/states"
|
||||
"github.com/opentofu/opentofu/internal/states/remote"
|
||||
"github.com/opentofu/opentofu/internal/tfdiags"
|
||||
@ -70,7 +71,7 @@ func TestBackendConfig_original(t *testing.T) {
|
||||
"dynamodb_table": "dynamoTable",
|
||||
}
|
||||
|
||||
b := backend.TestBackendConfig(t, New(), backend.TestWrapConfig(config)).(*Backend)
|
||||
b := backend.TestBackendConfig(t, New(encryption.StateEncryptionDisabled()), backend.TestWrapConfig(config)).(*Backend)
|
||||
|
||||
if b.awsConfig.Region != "us-west-1" {
|
||||
t.Fatalf("Incorrect region was populated")
|
||||
@ -134,7 +135,7 @@ func TestBackendConfig_InvalidRegion(t *testing.T) {
|
||||
|
||||
for name, tc := range cases {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
b := New()
|
||||
b := New(encryption.StateEncryptionDisabled())
|
||||
configSchema := populateSchema(t, b.ConfigSchema(), hcl2shim.HCL2ValueFromConfigValue(tc.config))
|
||||
|
||||
configSchema, diags := b.PrepareConfig(configSchema)
|
||||
@ -181,7 +182,7 @@ func TestBackendConfig_RegionEnvVar(t *testing.T) {
|
||||
t.Setenv(k, v)
|
||||
}
|
||||
|
||||
b := backend.TestBackendConfig(t, New(), backend.TestWrapConfig(config)).(*Backend)
|
||||
b := backend.TestBackendConfig(t, New(encryption.StateEncryptionDisabled()), backend.TestWrapConfig(config)).(*Backend)
|
||||
|
||||
if b.awsConfig.Region != "us-west-1" {
|
||||
t.Fatalf("Incorrect region was populated")
|
||||
@ -235,7 +236,7 @@ func TestBackendConfig_DynamoDBEndpoint(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
backend.TestBackendConfig(t, New(), backend.TestWrapConfig(config))
|
||||
backend.TestBackendConfig(t, New(encryption.StateEncryptionDisabled()), backend.TestWrapConfig(config))
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -285,7 +286,7 @@ func TestBackendConfig_S3Endpoint(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
backend.TestBackendConfig(t, New(), backend.TestWrapConfig(config))
|
||||
backend.TestBackendConfig(t, New(encryption.StateEncryptionDisabled()), backend.TestWrapConfig(config))
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -355,7 +356,7 @@ func TestBackendConfig_STSEndpoint(t *testing.T) {
|
||||
config["sts_endpoint"] = endpoint
|
||||
}
|
||||
|
||||
b := New()
|
||||
b := New(encryption.StateEncryptionDisabled())
|
||||
configSchema := populateSchema(t, b.ConfigSchema(), hcl2shim.HCL2ValueFromConfigValue(config))
|
||||
|
||||
configSchema, diags := b.PrepareConfig(configSchema)
|
||||
@ -593,7 +594,7 @@ func TestBackendConfig_AssumeRole(t *testing.T) {
|
||||
|
||||
testCase.Config["sts_endpoint"] = endpoint
|
||||
|
||||
b := New()
|
||||
b := New(encryption.StateEncryptionDisabled())
|
||||
diags := b.Configure(populateSchema(t, b.ConfigSchema(), hcl2shim.HCL2ValueFromConfigValue(testCase.Config)))
|
||||
|
||||
if diags.HasErrors() {
|
||||
@ -776,7 +777,7 @@ func TestBackendConfig_PrepareConfigValidation(t *testing.T) {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
servicemocks.StashEnv(t)
|
||||
|
||||
b := New()
|
||||
b := New(encryption.StateEncryptionDisabled())
|
||||
|
||||
_, valDiags := b.PrepareConfig(populateSchema(t, b.ConfigSchema(), tc.config))
|
||||
if tc.expectedErr != "" {
|
||||
@ -815,7 +816,7 @@ func TestBackendConfig_PrepareConfigValidationWarnings(t *testing.T) {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
servicemocks.StashEnv(t)
|
||||
|
||||
b := New()
|
||||
b := New(encryption.StateEncryptionDisabled())
|
||||
|
||||
_, diags := b.PrepareConfig(populateSchema(t, b.ConfigSchema(), tc.config))
|
||||
if tc.expectedWarn != "" {
|
||||
@ -878,7 +879,7 @@ func TestBackendConfig_PrepareConfigWithEnvVars(t *testing.T) {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
servicemocks.StashEnv(t)
|
||||
|
||||
b := New()
|
||||
b := New(encryption.StateEncryptionDisabled())
|
||||
|
||||
for k, v := range tc.vars {
|
||||
t.Setenv(k, v)
|
||||
@ -1043,7 +1044,7 @@ func TestBackendConfig_proxy(t *testing.T) {
|
||||
t.Setenv(k, v)
|
||||
}
|
||||
|
||||
b := New()
|
||||
b := New(encryption.StateEncryptionDisabled())
|
||||
|
||||
got := b.Configure(populateSchema(t, b.ConfigSchema(), tc.config))
|
||||
if got.HasErrors() != (tc.wantErrSubstr != "") {
|
||||
@ -1077,7 +1078,7 @@ func TestBackend(t *testing.T) {
|
||||
bucketName := fmt.Sprintf("%s-%x", testBucketPrefix, time.Now().Unix())
|
||||
keyName := "testState"
|
||||
|
||||
b := backend.TestBackendConfig(t, New(), backend.TestWrapConfig(map[string]interface{}{
|
||||
b := backend.TestBackendConfig(t, New(encryption.StateEncryptionDisabled()), backend.TestWrapConfig(map[string]interface{}{
|
||||
"bucket": bucketName,
|
||||
"key": keyName,
|
||||
"encrypt": true,
|
||||
@ -1097,7 +1098,7 @@ func TestBackendLocked(t *testing.T) {
|
||||
bucketName := fmt.Sprintf("%s-%x", testBucketPrefix, time.Now().Unix())
|
||||
keyName := "test/state"
|
||||
|
||||
b1 := backend.TestBackendConfig(t, New(), backend.TestWrapConfig(map[string]interface{}{
|
||||
b1 := backend.TestBackendConfig(t, New(encryption.StateEncryptionDisabled()), backend.TestWrapConfig(map[string]interface{}{
|
||||
"bucket": bucketName,
|
||||
"key": keyName,
|
||||
"encrypt": true,
|
||||
@ -1105,7 +1106,7 @@ func TestBackendLocked(t *testing.T) {
|
||||
"region": "us-west-1",
|
||||
})).(*Backend)
|
||||
|
||||
b2 := backend.TestBackendConfig(t, New(), backend.TestWrapConfig(map[string]interface{}{
|
||||
b2 := backend.TestBackendConfig(t, New(encryption.StateEncryptionDisabled()), backend.TestWrapConfig(map[string]interface{}{
|
||||
"bucket": bucketName,
|
||||
"key": keyName,
|
||||
"encrypt": true,
|
||||
@ -1156,7 +1157,7 @@ func TestBackendSSECustomerKeyConfig(t *testing.T) {
|
||||
"region": "us-west-1",
|
||||
}
|
||||
|
||||
b := New().(*Backend)
|
||||
b := New(encryption.StateEncryptionDisabled()).(*Backend)
|
||||
diags := b.Configure(populateSchema(t, b.ConfigSchema(), hcl2shim.HCL2ValueFromConfigValue(config)))
|
||||
|
||||
if testCase.expectedErr != "" {
|
||||
@ -1220,7 +1221,7 @@ func TestBackendSSECustomerKeyEnvVar(t *testing.T) {
|
||||
|
||||
t.Setenv("AWS_SSE_CUSTOMER_KEY", testCase.customerKey)
|
||||
|
||||
b := New().(*Backend)
|
||||
b := New(encryption.StateEncryptionDisabled()).(*Backend)
|
||||
diags := b.Configure(populateSchema(t, b.ConfigSchema(), hcl2shim.HCL2ValueFromConfigValue(config)))
|
||||
|
||||
if testCase.expectedErr != "" {
|
||||
@ -1256,7 +1257,7 @@ func TestBackendExtraPaths(t *testing.T) {
|
||||
bucketName := fmt.Sprintf("%s-%x", testBucketPrefix, time.Now().Unix())
|
||||
keyName := "test/state/tfstate"
|
||||
|
||||
b := backend.TestBackendConfig(t, New(), backend.TestWrapConfig(map[string]interface{}{
|
||||
b := backend.TestBackendConfig(t, New(encryption.StateEncryptionDisabled()), backend.TestWrapConfig(map[string]interface{}{
|
||||
"bucket": bucketName,
|
||||
"key": keyName,
|
||||
"encrypt": true,
|
||||
@ -1395,7 +1396,7 @@ func TestBackendPrefixInWorkspace(t *testing.T) {
|
||||
testACC(t)
|
||||
bucketName := fmt.Sprintf("%s-%x", testBucketPrefix, time.Now().Unix())
|
||||
|
||||
b := backend.TestBackendConfig(t, New(), backend.TestWrapConfig(map[string]interface{}{
|
||||
b := backend.TestBackendConfig(t, New(encryption.StateEncryptionDisabled()), backend.TestWrapConfig(map[string]interface{}{
|
||||
"bucket": bucketName,
|
||||
"key": "test-env.tfstate",
|
||||
"workspace_key_prefix": "env",
|
||||
@ -1424,7 +1425,7 @@ func TestKeyEnv(t *testing.T) {
|
||||
keyName := "some/paths/tfstate"
|
||||
|
||||
bucket0Name := fmt.Sprintf("%s-%x-0", testBucketPrefix, time.Now().Unix())
|
||||
b0 := backend.TestBackendConfig(t, New(), backend.TestWrapConfig(map[string]interface{}{
|
||||
b0 := backend.TestBackendConfig(t, New(encryption.StateEncryptionDisabled()), backend.TestWrapConfig(map[string]interface{}{
|
||||
"bucket": bucket0Name,
|
||||
"key": keyName,
|
||||
"encrypt": true,
|
||||
@ -1436,7 +1437,7 @@ func TestKeyEnv(t *testing.T) {
|
||||
defer deleteS3Bucket(ctx, t, b0.s3Client, bucket0Name)
|
||||
|
||||
bucket1Name := fmt.Sprintf("%s-%x-1", testBucketPrefix, time.Now().Unix())
|
||||
b1 := backend.TestBackendConfig(t, New(), backend.TestWrapConfig(map[string]interface{}{
|
||||
b1 := backend.TestBackendConfig(t, New(encryption.StateEncryptionDisabled()), backend.TestWrapConfig(map[string]interface{}{
|
||||
"bucket": bucket1Name,
|
||||
"key": keyName,
|
||||
"encrypt": true,
|
||||
@ -1447,7 +1448,7 @@ func TestKeyEnv(t *testing.T) {
|
||||
defer deleteS3Bucket(ctx, t, b1.s3Client, bucket1Name)
|
||||
|
||||
bucket2Name := fmt.Sprintf("%s-%x-2", testBucketPrefix, time.Now().Unix())
|
||||
b2 := backend.TestBackendConfig(t, New(), backend.TestWrapConfig(map[string]interface{}{
|
||||
b2 := backend.TestBackendConfig(t, New(encryption.StateEncryptionDisabled()), backend.TestWrapConfig(map[string]interface{}{
|
||||
"bucket": bucket2Name,
|
||||
"key": keyName,
|
||||
"encrypt": true,
|
||||
@ -1577,7 +1578,7 @@ func TestBackend_schemaCoercionMinimal(t *testing.T) {
|
||||
"bucket": cty.StringVal("my-bucket"),
|
||||
"key": cty.StringVal("state.tf"),
|
||||
})
|
||||
schema := New().ConfigSchema()
|
||||
schema := New(encryption.StateEncryptionDisabled()).ConfigSchema()
|
||||
_, err := schema.CoerceValue(example)
|
||||
if err != nil {
|
||||
t.Errorf("Unexpected error: %s", err.Error())
|
||||
|
@ -15,6 +15,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/opentofu/opentofu/internal/backend"
|
||||
"github.com/opentofu/opentofu/internal/encryption"
|
||||
"github.com/opentofu/opentofu/internal/states/remote"
|
||||
"github.com/opentofu/opentofu/internal/states/statefile"
|
||||
"github.com/opentofu/opentofu/internal/states/statemgr"
|
||||
@ -30,7 +31,7 @@ func TestRemoteClient(t *testing.T) {
|
||||
bucketName := fmt.Sprintf("%s-%x", testBucketPrefix, time.Now().Unix())
|
||||
keyName := "testState"
|
||||
|
||||
b := backend.TestBackendConfig(t, New(), backend.TestWrapConfig(map[string]interface{}{
|
||||
b := backend.TestBackendConfig(t, New(encryption.StateEncryptionDisabled()), backend.TestWrapConfig(map[string]interface{}{
|
||||
"bucket": bucketName,
|
||||
"key": keyName,
|
||||
"encrypt": true,
|
||||
@ -53,14 +54,14 @@ func TestRemoteClientLocks(t *testing.T) {
|
||||
bucketName := fmt.Sprintf("%s-%x", testBucketPrefix, time.Now().Unix())
|
||||
keyName := "testState"
|
||||
|
||||
b1 := backend.TestBackendConfig(t, New(), backend.TestWrapConfig(map[string]interface{}{
|
||||
b1 := backend.TestBackendConfig(t, New(encryption.StateEncryptionDisabled()), backend.TestWrapConfig(map[string]interface{}{
|
||||
"bucket": bucketName,
|
||||
"key": keyName,
|
||||
"encrypt": true,
|
||||
"dynamodb_table": bucketName,
|
||||
})).(*Backend)
|
||||
|
||||
b2 := backend.TestBackendConfig(t, New(), backend.TestWrapConfig(map[string]interface{}{
|
||||
b2 := backend.TestBackendConfig(t, New(encryption.StateEncryptionDisabled()), backend.TestWrapConfig(map[string]interface{}{
|
||||
"bucket": bucketName,
|
||||
"key": keyName,
|
||||
"encrypt": true,
|
||||
@ -92,14 +93,14 @@ func TestForceUnlock(t *testing.T) {
|
||||
bucketName := fmt.Sprintf("%s-force-%x", testBucketPrefix, time.Now().Unix())
|
||||
keyName := "testState"
|
||||
|
||||
b1 := backend.TestBackendConfig(t, New(), backend.TestWrapConfig(map[string]interface{}{
|
||||
b1 := backend.TestBackendConfig(t, New(encryption.StateEncryptionDisabled()), backend.TestWrapConfig(map[string]interface{}{
|
||||
"bucket": bucketName,
|
||||
"key": keyName,
|
||||
"encrypt": true,
|
||||
"dynamodb_table": bucketName,
|
||||
})).(*Backend)
|
||||
|
||||
b2 := backend.TestBackendConfig(t, New(), backend.TestWrapConfig(map[string]interface{}{
|
||||
b2 := backend.TestBackendConfig(t, New(encryption.StateEncryptionDisabled()), backend.TestWrapConfig(map[string]interface{}{
|
||||
"bucket": bucketName,
|
||||
"key": keyName,
|
||||
"encrypt": true,
|
||||
@ -170,7 +171,7 @@ func TestRemoteClient_clientMD5(t *testing.T) {
|
||||
bucketName := fmt.Sprintf("%s-%x", testBucketPrefix, time.Now().Unix())
|
||||
keyName := "testState"
|
||||
|
||||
b := backend.TestBackendConfig(t, New(), backend.TestWrapConfig(map[string]interface{}{
|
||||
b := backend.TestBackendConfig(t, New(encryption.StateEncryptionDisabled()), backend.TestWrapConfig(map[string]interface{}{
|
||||
"bucket": bucketName,
|
||||
"key": keyName,
|
||||
"dynamodb_table": bucketName,
|
||||
@ -219,7 +220,7 @@ func TestRemoteClient_stateChecksum(t *testing.T) {
|
||||
bucketName := fmt.Sprintf("%s-%x", testBucketPrefix, time.Now().Unix())
|
||||
keyName := "testState"
|
||||
|
||||
b1 := backend.TestBackendConfig(t, New(), backend.TestWrapConfig(map[string]interface{}{
|
||||
b1 := backend.TestBackendConfig(t, New(encryption.StateEncryptionDisabled()), backend.TestWrapConfig(map[string]interface{}{
|
||||
"bucket": bucketName,
|
||||
"key": keyName,
|
||||
"dynamodb_table": bucketName,
|
||||
@ -241,18 +242,18 @@ func TestRemoteClient_stateChecksum(t *testing.T) {
|
||||
s := statemgr.TestFullInitialState()
|
||||
sf := &statefile.File{State: s}
|
||||
var oldState bytes.Buffer
|
||||
if err := statefile.Write(sf, &oldState); err != nil {
|
||||
if err := statefile.Write(sf, &oldState, encryption.StateEncryptionDisabled()); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
sf.Serial++
|
||||
var newState bytes.Buffer
|
||||
if err := statefile.Write(sf, &newState); err != nil {
|
||||
if err := statefile.Write(sf, &newState, encryption.StateEncryptionDisabled()); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Use b2 without a dynamodb_table to bypass the lock table to write the state directly.
|
||||
// client2 will write the "incorrect" state, simulating s3 eventually consistency delays
|
||||
b2 := backend.TestBackendConfig(t, New(), backend.TestWrapConfig(map[string]interface{}{
|
||||
b2 := backend.TestBackendConfig(t, New(encryption.StateEncryptionDisabled()), backend.TestWrapConfig(map[string]interface{}{
|
||||
"bucket": bucketName,
|
||||
"key": keyName,
|
||||
})).(*Backend)
|
||||
|
@ -25,6 +25,7 @@ import (
|
||||
"github.com/mitchellh/colorstring"
|
||||
"github.com/opentofu/opentofu/internal/backend"
|
||||
"github.com/opentofu/opentofu/internal/configs/configschema"
|
||||
"github.com/opentofu/opentofu/internal/encryption"
|
||||
"github.com/opentofu/opentofu/internal/httpclient"
|
||||
"github.com/opentofu/opentofu/internal/logging"
|
||||
"github.com/opentofu/opentofu/internal/states/remote"
|
||||
@ -95,6 +96,8 @@ type Remote struct {
|
||||
// version. This will also cause VerifyWorkspaceTerraformVersion to return
|
||||
// a warning diagnostic instead of an error.
|
||||
ignoreVersionConflict bool
|
||||
|
||||
encryption encryption.StateEncryption
|
||||
}
|
||||
|
||||
var _ backend.Backend = (*Remote)(nil)
|
||||
@ -102,9 +105,10 @@ var _ backend.Enhanced = (*Remote)(nil)
|
||||
var _ backend.Local = (*Remote)(nil)
|
||||
|
||||
// New creates a new initialized remote backend.
|
||||
func New(services *disco.Disco) *Remote {
|
||||
func New(services *disco.Disco, enc encryption.StateEncryption) *Remote {
|
||||
return &Remote{
|
||||
services: services,
|
||||
services: services,
|
||||
encryption: enc,
|
||||
}
|
||||
}
|
||||
|
||||
@ -374,7 +378,7 @@ func (b *Remote) Configure(obj cty.Value) tfdiags.Diagnostics {
|
||||
}
|
||||
|
||||
// Configure a local backend for when we need to run operations locally.
|
||||
b.local = backendLocal.NewWithBackend(b)
|
||||
b.local = backendLocal.NewWithBackend(b, nil)
|
||||
b.forceLocal = b.forceLocal || !entitlements.Operations
|
||||
|
||||
// Enable retries for server errors as the backend is now fully configured.
|
||||
@ -704,9 +708,8 @@ func (b *Remote) StateMgr(name string) (statemgr.Full, error) {
|
||||
runID: os.Getenv("TFE_RUN_ID"),
|
||||
}
|
||||
|
||||
return &remote.State{
|
||||
Client: client,
|
||||
|
||||
state := remote.NewState(client, b.encryption)
|
||||
if client.runID != "" {
|
||||
// client.runID will be set if we're running a Terraform Cloud
|
||||
// or Terraform Enterprise remote execution environment, in which
|
||||
// case we'll disable intermediate snapshots to avoid extra storage
|
||||
@ -714,8 +717,9 @@ func (b *Remote) StateMgr(name string) (statemgr.Full, error) {
|
||||
// Other implementations of the remote state protocol should not run
|
||||
// in contexts where there's a "TFE Run ID" and so are not affected
|
||||
// by this special case.
|
||||
DisableIntermediateSnapshots: client.runID != "",
|
||||
}, nil
|
||||
state.DisableIntermediateSnapshots()
|
||||
}
|
||||
return state, nil
|
||||
}
|
||||
|
||||
func isLocalExecutionMode(execMode string) bool {
|
||||
|
@ -18,6 +18,7 @@ import (
|
||||
tfe "github.com/hashicorp/go-tfe"
|
||||
|
||||
"github.com/opentofu/opentofu/internal/command/jsonstate"
|
||||
"github.com/opentofu/opentofu/internal/encryption"
|
||||
"github.com/opentofu/opentofu/internal/states/remote"
|
||||
"github.com/opentofu/opentofu/internal/states/statefile"
|
||||
"github.com/opentofu/opentofu/internal/states/statemgr"
|
||||
@ -95,7 +96,8 @@ func (r *remoteClient) Put(state []byte) error {
|
||||
ctx := context.Background()
|
||||
|
||||
// Read the raw state into a OpenTofu state.
|
||||
stateFile, err := statefile.Read(bytes.NewReader(state))
|
||||
// State Encryption is not supported for the remote backend
|
||||
stateFile, err := statefile.Read(bytes.NewReader(state), encryption.StateEncryptionDisabled())
|
||||
if err != nil {
|
||||
return fmt.Errorf("error reading state: %w", err)
|
||||
}
|
||||
|
@ -11,6 +11,7 @@ import (
|
||||
|
||||
"github.com/opentofu/opentofu/internal/backend"
|
||||
"github.com/opentofu/opentofu/internal/cloud"
|
||||
"github.com/opentofu/opentofu/internal/encryption"
|
||||
"github.com/opentofu/opentofu/internal/states"
|
||||
"github.com/opentofu/opentofu/internal/states/remote"
|
||||
"github.com/opentofu/opentofu/internal/states/statefile"
|
||||
@ -52,7 +53,7 @@ func TestRemoteClient_Put_withRunID(t *testing.T) {
|
||||
// Create a new empty state.
|
||||
sf := statefile.New(states.NewState(), "", 0)
|
||||
var buf bytes.Buffer
|
||||
statefile.Write(sf, &buf)
|
||||
statefile.Write(sf, &buf, encryption.StateEncryptionDisabled())
|
||||
|
||||
// Store the new state to verify (this will be done
|
||||
// by the mock that is used) that the run ID is set.
|
||||
|
@ -16,6 +16,7 @@ import (
|
||||
version "github.com/hashicorp/go-version"
|
||||
"github.com/hashicorp/terraform-svchost/disco"
|
||||
"github.com/opentofu/opentofu/internal/backend"
|
||||
"github.com/opentofu/opentofu/internal/encryption"
|
||||
"github.com/opentofu/opentofu/internal/states/statemgr"
|
||||
"github.com/opentofu/opentofu/internal/tfdiags"
|
||||
tfversion "github.com/opentofu/opentofu/version"
|
||||
@ -25,8 +26,8 @@ import (
|
||||
)
|
||||
|
||||
func TestRemote(t *testing.T) {
|
||||
var _ backend.Enhanced = New(nil)
|
||||
var _ backend.CLI = New(nil)
|
||||
var _ backend.Enhanced = New(nil, encryption.StateEncryptionDisabled())
|
||||
var _ backend.CLI = New(nil, encryption.StateEncryptionDisabled())
|
||||
}
|
||||
|
||||
func TestRemote_backendDefault(t *testing.T) {
|
||||
@ -153,7 +154,7 @@ func TestRemote_config(t *testing.T) {
|
||||
|
||||
for name, tc := range cases {
|
||||
s := testServer(t)
|
||||
b := New(testDisco(s))
|
||||
b := New(testDisco(s), encryption.StateEncryptionDisabled())
|
||||
|
||||
// Validate
|
||||
_, valDiags := b.PrepareConfig(tc.config)
|
||||
@ -228,7 +229,7 @@ func TestRemote_versionConstraints(t *testing.T) {
|
||||
|
||||
for name, tc := range cases {
|
||||
s := testServer(t)
|
||||
b := New(testDisco(s))
|
||||
b := New(testDisco(s), encryption.StateEncryptionDisabled())
|
||||
|
||||
// Set the version for this test.
|
||||
tfversion.Prerelease = tc.prerelease
|
||||
@ -783,7 +784,7 @@ func TestRemote_VerifyWorkspaceTerraformVersion_ignoreFlagSet(t *testing.T) {
|
||||
|
||||
func TestRemote_ServiceDiscoveryAliases(t *testing.T) {
|
||||
s := testServer(t)
|
||||
b := New(testDisco(s))
|
||||
b := New(testDisco(s), encryption.StateEncryptionDisabled())
|
||||
|
||||
diag := b.Configure(cty.ObjectVal(map[string]cty.Value{
|
||||
"hostname": cty.StringVal(mockedBackendHost),
|
||||
|
@ -24,6 +24,7 @@ import (
|
||||
"github.com/opentofu/opentofu/internal/cloud"
|
||||
"github.com/opentofu/opentofu/internal/configs"
|
||||
"github.com/opentofu/opentofu/internal/configs/configschema"
|
||||
"github.com/opentofu/opentofu/internal/encryption"
|
||||
"github.com/opentofu/opentofu/internal/httpclient"
|
||||
"github.com/opentofu/opentofu/internal/providers"
|
||||
"github.com/opentofu/opentofu/internal/states/remote"
|
||||
@ -123,7 +124,7 @@ func testRemoteClient(t *testing.T) remote.Client {
|
||||
|
||||
func testBackend(t *testing.T, obj cty.Value) (*Remote, func()) {
|
||||
s := testServer(t)
|
||||
b := New(testDisco(s))
|
||||
b := New(testDisco(s), encryption.StateEncryptionDisabled())
|
||||
|
||||
// Configure the backend so the client is created.
|
||||
newObj, valDiags := b.PrepareConfig(obj)
|
||||
@ -181,7 +182,7 @@ func testBackend(t *testing.T, obj cty.Value) (*Remote, func()) {
|
||||
}
|
||||
|
||||
func testLocalBackend(t *testing.T, remote *Remote) backend.Enhanced {
|
||||
b := backendLocal.NewWithBackend(remote)
|
||||
b := backendLocal.NewWithBackend(remote, nil)
|
||||
|
||||
// Add a test provider to the local backend.
|
||||
p := backendLocal.TestLocalProvider(t, b, "null", providers.ProviderSchema{
|
||||
|
@ -12,6 +12,7 @@ import (
|
||||
"github.com/opentofu/opentofu/internal/backend"
|
||||
"github.com/opentofu/opentofu/internal/backend/remote"
|
||||
"github.com/opentofu/opentofu/internal/configs/configschema"
|
||||
"github.com/opentofu/opentofu/internal/encryption"
|
||||
"github.com/opentofu/opentofu/internal/providers"
|
||||
"github.com/opentofu/opentofu/internal/tfdiags"
|
||||
"github.com/zclconf/go-cty/cty"
|
||||
@ -211,7 +212,7 @@ func getBackend(cfg cty.Value) (backend.Backend, cty.Value, tfdiags.Diagnostics)
|
||||
))
|
||||
return nil, cty.NilVal, diags
|
||||
}
|
||||
b := f()
|
||||
b := f(encryption.StateEncryptionTODO())
|
||||
|
||||
config := cfg.GetAttr("config")
|
||||
if config.IsNull() {
|
||||
|
@ -13,6 +13,7 @@ import (
|
||||
"github.com/apparentlymart/go-dump/dump"
|
||||
"github.com/opentofu/opentofu/internal/backend"
|
||||
"github.com/opentofu/opentofu/internal/configs/configschema"
|
||||
"github.com/opentofu/opentofu/internal/encryption"
|
||||
"github.com/opentofu/opentofu/internal/states/statemgr"
|
||||
"github.com/opentofu/opentofu/internal/tfdiags"
|
||||
"github.com/zclconf/go-cty/cty"
|
||||
@ -320,7 +321,7 @@ func TestState_validation(t *testing.T) {
|
||||
// the validation step in isolation does not attempt to configure
|
||||
// the backend.
|
||||
overrideBackendFactories = map[string]backend.InitFn{
|
||||
"failsconfigure": func() backend.Backend {
|
||||
"failsconfigure": func(enc encryption.StateEncryption) backend.Backend {
|
||||
return backendFailsConfigure{}
|
||||
},
|
||||
}
|
||||
|
@ -30,6 +30,7 @@ import (
|
||||
"github.com/opentofu/opentofu/internal/backend"
|
||||
"github.com/opentofu/opentofu/internal/command/jsonformat"
|
||||
"github.com/opentofu/opentofu/internal/configs/configschema"
|
||||
"github.com/opentofu/opentofu/internal/encryption"
|
||||
"github.com/opentofu/opentofu/internal/httpclient"
|
||||
"github.com/opentofu/opentofu/internal/plans"
|
||||
"github.com/opentofu/opentofu/internal/states/statemgr"
|
||||
@ -107,6 +108,8 @@ type Cloud struct {
|
||||
// input stores the value of the -input flag, since it will be used
|
||||
// to determine whether or not to ask the user for approval of a run.
|
||||
input bool
|
||||
|
||||
encryption encryption.StateEncryption
|
||||
}
|
||||
|
||||
var _ backend.Backend = (*Cloud)(nil)
|
||||
@ -114,9 +117,10 @@ var _ backend.Enhanced = (*Cloud)(nil)
|
||||
var _ backend.Local = (*Cloud)(nil)
|
||||
|
||||
// New creates a new initialized cloud backend.
|
||||
func New(services *disco.Disco) *Cloud {
|
||||
func New(services *disco.Disco, enc encryption.StateEncryption) *Cloud {
|
||||
return &Cloud{
|
||||
services: services,
|
||||
services: services,
|
||||
encryption: enc,
|
||||
}
|
||||
}
|
||||
|
||||
@ -409,7 +413,7 @@ func (b *Cloud) Configure(obj cty.Value) tfdiags.Diagnostics {
|
||||
}
|
||||
|
||||
// Configure a local backend for when we need to run operations locally.
|
||||
b.local = backendLocal.NewWithBackend(b)
|
||||
b.local = backendLocal.NewWithBackend(b, nil)
|
||||
b.forceLocal = b.forceLocal || !entitlements.Operations
|
||||
|
||||
// Enable retries for server errors as the backend is now fully configured.
|
||||
@ -641,7 +645,7 @@ func (b *Cloud) DeleteWorkspace(name string, force bool) error {
|
||||
}
|
||||
|
||||
// Configure the remote workspace name.
|
||||
State := &State{tfeClient: b.client, organization: b.organization, workspace: workspace, enableIntermediateSnapshots: false}
|
||||
State := &State{tfeClient: b.client, organization: b.organization, workspace: workspace, enableIntermediateSnapshots: false, encryption: b.encryption}
|
||||
return State.Delete(force)
|
||||
}
|
||||
|
||||
@ -776,7 +780,7 @@ func (b *Cloud) StateMgr(name string) (statemgr.Full, error) {
|
||||
}
|
||||
}
|
||||
|
||||
return &State{tfeClient: b.client, organization: b.organization, workspace: workspace, enableIntermediateSnapshots: false}, nil
|
||||
return &State{tfeClient: b.client, organization: b.organization, workspace: workspace, enableIntermediateSnapshots: false, encryption: b.encryption}, nil
|
||||
}
|
||||
|
||||
// Operation implements backend.Enhanced.
|
||||
|
@ -15,6 +15,7 @@ import (
|
||||
tfe "github.com/hashicorp/go-tfe"
|
||||
version "github.com/hashicorp/go-version"
|
||||
"github.com/opentofu/opentofu/internal/backend"
|
||||
"github.com/opentofu/opentofu/internal/encryption"
|
||||
"github.com/opentofu/opentofu/internal/tfdiags"
|
||||
tfversion "github.com/opentofu/opentofu/version"
|
||||
"github.com/zclconf/go-cty/cty"
|
||||
@ -23,8 +24,8 @@ import (
|
||||
)
|
||||
|
||||
func TestCloud(t *testing.T) {
|
||||
var _ backend.Enhanced = New(nil)
|
||||
var _ backend.CLI = New(nil)
|
||||
var _ backend.Enhanced = New(nil, encryption.StateEncryptionDisabled())
|
||||
var _ backend.CLI = New(nil, encryption.StateEncryptionDisabled())
|
||||
}
|
||||
|
||||
func TestCloud_backendWithName(t *testing.T) {
|
||||
@ -55,7 +56,7 @@ func TestCloud_backendWithName(t *testing.T) {
|
||||
|
||||
func TestCloud_backendWithoutHost(t *testing.T) {
|
||||
s := testServer(t)
|
||||
b := New(testDisco(s))
|
||||
b := New(testDisco(s), encryption.StateEncryptionDisabled())
|
||||
|
||||
obj := cty.ObjectVal(map[string]cty.Value{
|
||||
"hostname": cty.NullVal(cty.String),
|
||||
@ -175,7 +176,7 @@ func TestCloud_PrepareConfig(t *testing.T) {
|
||||
for name, tc := range cases {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
s := testServer(t)
|
||||
b := New(testDisco(s))
|
||||
b := New(testDisco(s), encryption.StateEncryptionDisabled())
|
||||
|
||||
// Validate
|
||||
_, valDiags := b.PrepareConfig(tc.config)
|
||||
@ -326,7 +327,7 @@ func TestCloud_PrepareConfigWithEnvVars(t *testing.T) {
|
||||
for name, tc := range cases {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
s := testServer(t)
|
||||
b := New(testDisco(s))
|
||||
b := New(testDisco(s), encryption.StateEncryptionDisabled())
|
||||
|
||||
for k, v := range tc.vars {
|
||||
t.Setenv(k, v)
|
||||
@ -487,7 +488,7 @@ func TestCloud_configVerifyMinimumTFEVersion(t *testing.T) {
|
||||
}
|
||||
s := testServerWithHandlers(handlers)
|
||||
|
||||
b := New(testDisco(s))
|
||||
b := New(testDisco(s), encryption.StateEncryptionDisabled())
|
||||
|
||||
confDiags := b.Configure(config)
|
||||
if confDiags.Err() == nil {
|
||||
@ -524,7 +525,7 @@ func TestCloud_configVerifyMinimumTFEVersionInAutomation(t *testing.T) {
|
||||
}
|
||||
s := testServerWithHandlers(handlers)
|
||||
|
||||
b := New(testDisco(s))
|
||||
b := New(testDisco(s), encryption.StateEncryptionDisabled())
|
||||
b.runningInAutomation = true
|
||||
|
||||
confDiags := b.Configure(config)
|
||||
@ -1286,7 +1287,7 @@ func TestCloudBackend_DeleteWorkspace_DoesNotExist(t *testing.T) {
|
||||
|
||||
func TestCloud_ServiceDiscoveryAliases(t *testing.T) {
|
||||
s := testServer(t)
|
||||
b := New(testDisco(s))
|
||||
b := New(testDisco(s), encryption.StateEncryptionDisabled())
|
||||
|
||||
diag := b.Configure(cty.ObjectVal(map[string]cty.Value{
|
||||
"hostname": cty.StringVal(tfeHost),
|
||||
|
@ -29,6 +29,7 @@ import (
|
||||
|
||||
"github.com/opentofu/opentofu/internal/backend/local"
|
||||
"github.com/opentofu/opentofu/internal/command/jsonstate"
|
||||
"github.com/opentofu/opentofu/internal/encryption"
|
||||
"github.com/opentofu/opentofu/internal/states"
|
||||
"github.com/opentofu/opentofu/internal/states/remote"
|
||||
"github.com/opentofu/opentofu/internal/states/statefile"
|
||||
@ -79,6 +80,8 @@ type State struct {
|
||||
// If the header X-Terraform-Snapshot-Interval is present then
|
||||
// we will enable snapshots
|
||||
enableIntermediateSnapshots bool
|
||||
|
||||
encryption encryption.StateEncryption
|
||||
}
|
||||
|
||||
var ErrStateVersionUnauthorizedUpgradeState = errors.New(strings.TrimSpace(`
|
||||
@ -204,7 +207,7 @@ func (s *State) PersistState(schemas *tofu.Schemas) error {
|
||||
f := statefile.New(s.state, s.lineage, s.serial)
|
||||
|
||||
var buf bytes.Buffer
|
||||
err := statefile.Write(f, &buf)
|
||||
err := statefile.Write(f, &buf, s.encryption)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -217,7 +220,7 @@ func (s *State) PersistState(schemas *tofu.Schemas) error {
|
||||
}
|
||||
}
|
||||
|
||||
stateFile, err := statefile.Read(bytes.NewReader(buf.Bytes()))
|
||||
stateFile, err := statefile.Read(bytes.NewReader(buf.Bytes()), s.encryption)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to read state: %w", err)
|
||||
}
|
||||
@ -387,7 +390,7 @@ func (s *State) refreshState() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
stateFile, err := statefile.Read(bytes.NewReader(payload.Data))
|
||||
stateFile, err := statefile.Read(bytes.NewReader(payload.Data), s.encryption)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -15,6 +15,7 @@ import (
|
||||
tfe "github.com/hashicorp/go-tfe"
|
||||
"github.com/opentofu/opentofu/internal/addrs"
|
||||
"github.com/opentofu/opentofu/internal/backend/local"
|
||||
"github.com/opentofu/opentofu/internal/encryption"
|
||||
"github.com/opentofu/opentofu/internal/states"
|
||||
"github.com/opentofu/opentofu/internal/states/statefile"
|
||||
"github.com/opentofu/opentofu/internal/states/statemgr"
|
||||
@ -42,7 +43,7 @@ func TestState_GetRootOutputValues(t *testing.T) {
|
||||
|
||||
state := &State{tfeClient: b.client, organization: b.organization, workspace: &tfe.Workspace{
|
||||
ID: "ws-abcd",
|
||||
}}
|
||||
}, encryption: encryption.StateEncryptionDisabled()}
|
||||
outputs, err := state.GetRootOutputValues()
|
||||
|
||||
if err != nil {
|
||||
@ -94,7 +95,7 @@ func TestState(t *testing.T) {
|
||||
var buf bytes.Buffer
|
||||
s := statemgr.TestFullInitialState()
|
||||
sf := statefile.New(s, "stub-lineage", 2)
|
||||
err := statefile.Write(sf, &buf)
|
||||
err := statefile.Write(sf, &buf, encryption.StateEncryptionDisabled())
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
|
@ -31,6 +31,7 @@ import (
|
||||
"github.com/opentofu/opentofu/internal/backend"
|
||||
"github.com/opentofu/opentofu/internal/configs"
|
||||
"github.com/opentofu/opentofu/internal/configs/configschema"
|
||||
"github.com/opentofu/opentofu/internal/encryption"
|
||||
"github.com/opentofu/opentofu/internal/httpclient"
|
||||
"github.com/opentofu/opentofu/internal/providers"
|
||||
"github.com/opentofu/opentofu/internal/states"
|
||||
@ -242,7 +243,7 @@ func testBackend(t *testing.T, obj cty.Value, handlers map[string]func(http.Resp
|
||||
} else {
|
||||
s = testServer(t)
|
||||
}
|
||||
b := New(testDisco(s))
|
||||
b := New(testDisco(s), encryption.StateEncryptionDisabled())
|
||||
|
||||
// Configure the backend so the client is created.
|
||||
newObj, valDiags := b.PrepareConfig(obj)
|
||||
@ -319,7 +320,7 @@ func testUnconfiguredBackend(t *testing.T) (*Cloud, func()) {
|
||||
skipIfTFENotEnabled(t)
|
||||
|
||||
s := testServer(t)
|
||||
b := New(testDisco(s))
|
||||
b := New(testDisco(s), encryption.StateEncryptionDisabled())
|
||||
|
||||
// Normally, the client is created during configuration, but the configuration uses the
|
||||
// client to read entitlements.
|
||||
@ -369,7 +370,7 @@ func testUnconfiguredBackend(t *testing.T) (*Cloud, func()) {
|
||||
func testLocalBackend(t *testing.T, cloud *Cloud) backend.Enhanced {
|
||||
skipIfTFENotEnabled(t)
|
||||
|
||||
b := backendLocal.NewWithBackend(cloud)
|
||||
b := backendLocal.NewWithBackend(cloud, nil)
|
||||
|
||||
// Add a test provider to the local backend.
|
||||
p := backendLocal.TestLocalProvider(t, b, "null", providers.ProviderSchema{
|
||||
@ -426,7 +427,7 @@ func testServerWithSnapshotsEnabled(t *testing.T, enabled bool) *httptest.Server
|
||||
fakeState := states.NewState()
|
||||
fakeStateFile := statefile.New(fakeState, "boop", 1)
|
||||
var buf bytes.Buffer
|
||||
statefile.Write(fakeStateFile, &buf)
|
||||
statefile.Write(fakeStateFile, &buf, encryption.StateEncryptionDisabled())
|
||||
respBody := buf.Bytes()
|
||||
w.Header().Set("content-type", "application/json")
|
||||
w.Header().Set("content-length", strconv.FormatInt(int64(len(respBody)), 10))
|
||||
|
@ -16,6 +16,7 @@ import (
|
||||
|
||||
"github.com/opentofu/opentofu/internal/addrs"
|
||||
"github.com/opentofu/opentofu/internal/configs/configschema"
|
||||
"github.com/opentofu/opentofu/internal/encryption"
|
||||
"github.com/opentofu/opentofu/internal/providers"
|
||||
"github.com/opentofu/opentofu/internal/states"
|
||||
"github.com/opentofu/opentofu/internal/states/statefile"
|
||||
@ -92,7 +93,7 @@ func TestApply_destroy(t *testing.T) {
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
stateFile, err := statefile.Read(f)
|
||||
stateFile, err := statefile.Read(f, encryption.StateEncryptionDisabled())
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
@ -112,7 +113,7 @@ func TestApply_destroy(t *testing.T) {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
|
||||
backupStateFile, err := statefile.Read(f)
|
||||
backupStateFile, err := statefile.Read(f, encryption.StateEncryptionDisabled())
|
||||
f.Close()
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
@ -488,7 +489,7 @@ func TestApply_destroyTargetedDependencies(t *testing.T) {
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
stateFile, err := statefile.Read(f)
|
||||
stateFile, err := statefile.Read(f, encryption.StateEncryptionDisabled())
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
@ -507,7 +508,7 @@ func TestApply_destroyTargetedDependencies(t *testing.T) {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
|
||||
backupStateFile, err := statefile.Read(f)
|
||||
backupStateFile, err := statefile.Read(f, encryption.StateEncryptionDisabled())
|
||||
f.Close()
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
@ -639,7 +640,7 @@ func TestApply_destroyTargeted(t *testing.T) {
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
stateFile, err := statefile.Read(f)
|
||||
stateFile, err := statefile.Read(f, encryption.StateEncryptionDisabled())
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
@ -659,7 +660,7 @@ func TestApply_destroyTargeted(t *testing.T) {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
|
||||
backupStateFile, err := statefile.Read(f)
|
||||
backupStateFile, err := statefile.Read(f, encryption.StateEncryptionDisabled())
|
||||
f.Close()
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
|
@ -24,6 +24,7 @@ import (
|
||||
|
||||
"github.com/opentofu/opentofu/internal/addrs"
|
||||
"github.com/opentofu/opentofu/internal/configs/configschema"
|
||||
"github.com/opentofu/opentofu/internal/encryption"
|
||||
"github.com/opentofu/opentofu/internal/plans"
|
||||
"github.com/opentofu/opentofu/internal/providers"
|
||||
"github.com/opentofu/opentofu/internal/states"
|
||||
@ -450,7 +451,7 @@ func TestApply_defaultState(t *testing.T) {
|
||||
}
|
||||
|
||||
// create an existing state file
|
||||
if err := statemgr.WriteAndPersist(statemgr.NewFilesystem(statePath), states.NewState(), nil); err != nil {
|
||||
if err := statemgr.WriteAndPersist(statemgr.NewFilesystem(statePath, encryption.StateEncryptionDisabled()), states.NewState(), nil); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
@ -738,7 +739,7 @@ func TestApply_plan_backup(t *testing.T) {
|
||||
}
|
||||
|
||||
// create a state file that needs to be backed up
|
||||
fs := statemgr.NewFilesystem(statePath)
|
||||
fs := statemgr.NewFilesystem(statePath, encryption.StateEncryptionDisabled())
|
||||
fs.StateSnapshotMeta()
|
||||
if err := statemgr.WriteAndPersist(fs, states.NewState(), nil); err != nil {
|
||||
t.Fatal(err)
|
||||
|
@ -327,7 +327,7 @@ func writeStateForTesting(state *states.State, w io.Writer) error {
|
||||
Lineage: "fake-for-testing",
|
||||
State: state,
|
||||
}
|
||||
return statefile.Write(sf, w)
|
||||
return statefile.Write(sf, w, encryption.StateEncryptionDisabled())
|
||||
}
|
||||
|
||||
// testStateMgrCurrentLineage returns the current lineage for the given state
|
||||
@ -482,7 +482,7 @@ func testStateRead(t *testing.T, path string) *states.State {
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
sf, err := statefile.Read(f)
|
||||
sf, err := statefile.Read(f, encryption.StateEncryptionDisabled())
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
@ -760,7 +760,7 @@ func testBackendState(t *testing.T, s *states.State, c int) (*legacy.State, *htt
|
||||
|
||||
// If a state was given, make sure we calculate the proper b64md5
|
||||
if s != nil {
|
||||
err := statefile.Write(&statefile.File{State: s}, buf)
|
||||
err := statefile.Write(&statefile.File{State: s}, buf, encryption.StateEncryptionDisabled())
|
||||
if err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
@ -774,7 +774,7 @@ func testBackendState(t *testing.T, s *states.State, c int) (*legacy.State, *htt
|
||||
Type: "http",
|
||||
Config: configs.SynthBody("<testBackendState>", map[string]cty.Value{}),
|
||||
}
|
||||
b := backendInit.Backend("http")()
|
||||
b := backendInit.Backend("http")(encryption.StateEncryptionDisabled())
|
||||
configSchema := b.ConfigSchema()
|
||||
hash := backendConfig.Hash(configSchema)
|
||||
|
||||
@ -833,7 +833,7 @@ func testRemoteState(t *testing.T, s *states.State, c int) (*legacy.State, *http
|
||||
retState.Backend = b
|
||||
|
||||
if s != nil {
|
||||
err := statefile.Write(&statefile.File{State: s}, buf)
|
||||
err := statefile.Write(&statefile.File{State: s}, buf, encryption.StateEncryptionDisabled())
|
||||
if err != nil {
|
||||
t.Fatalf("failed to write initial state: %v", err)
|
||||
}
|
||||
|
@ -478,7 +478,7 @@ func (c *InitCommand) initBackend(ctx context.Context, root *configs.Module, ext
|
||||
return nil, true, diags
|
||||
}
|
||||
|
||||
b := bf()
|
||||
b := bf(nil) // This is only used to get the schema, encryption should panic if attempted
|
||||
backendSchema := b.ConfigSchema()
|
||||
backendConfig = root.Backend
|
||||
|
||||
|
@ -27,6 +27,7 @@ import (
|
||||
"github.com/opentofu/opentofu/internal/configs"
|
||||
"github.com/opentofu/opentofu/internal/configs/configschema"
|
||||
"github.com/opentofu/opentofu/internal/depsfile"
|
||||
"github.com/opentofu/opentofu/internal/encryption"
|
||||
"github.com/opentofu/opentofu/internal/getproviders"
|
||||
"github.com/opentofu/opentofu/internal/providercache"
|
||||
"github.com/opentofu/opentofu/internal/states"
|
||||
@ -1262,7 +1263,7 @@ func TestInit_inputFalse(t *testing.T) {
|
||||
false, // not sensitive
|
||||
)
|
||||
})
|
||||
if err := statemgr.WriteAndPersist(statemgr.NewFilesystem("foo"), fooState, nil); err != nil {
|
||||
if err := statemgr.WriteAndPersist(statemgr.NewFilesystem("foo", encryption.StateEncryptionDisabled()), fooState, nil); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
barState := states.BuildState(func(s *states.SyncState) {
|
||||
@ -1272,7 +1273,7 @@ func TestInit_inputFalse(t *testing.T) {
|
||||
false, // not sensitive
|
||||
)
|
||||
})
|
||||
if err := statemgr.WriteAndPersist(statemgr.NewFilesystem("bar"), barState, nil); err != nil {
|
||||
if err := statemgr.WriteAndPersist(statemgr.NewFilesystem("bar", encryption.StateEncryptionDisabled()), barState, nil); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
|
@ -30,6 +30,7 @@ import (
|
||||
"github.com/opentofu/opentofu/internal/command/clistate"
|
||||
"github.com/opentofu/opentofu/internal/command/views"
|
||||
"github.com/opentofu/opentofu/internal/configs"
|
||||
"github.com/opentofu/opentofu/internal/encryption"
|
||||
"github.com/opentofu/opentofu/internal/plans"
|
||||
"github.com/opentofu/opentofu/internal/states/statemgr"
|
||||
"github.com/opentofu/opentofu/internal/tfdiags"
|
||||
@ -181,7 +182,7 @@ func (m *Meta) Backend(opts *BackendOpts) (backend.Enhanced, tfdiags.Diagnostics
|
||||
}
|
||||
|
||||
// Build the local backend
|
||||
local := backendLocal.NewWithBackend(b)
|
||||
local := backendLocal.NewWithBackend(b, encryption.StateEncryptionTODO())
|
||||
if err := local.CLIInit(cliOpts); err != nil {
|
||||
// Local backend isn't allowed to fail. It would be a bug.
|
||||
panic(err)
|
||||
@ -312,7 +313,7 @@ func (m *Meta) BackendForLocalPlan(settings plans.Backend) (backend.Enhanced, tf
|
||||
diags = diags.Append(fmt.Errorf(strings.TrimSpace(errBackendSavedUnknown), settings.Type))
|
||||
return nil, diags
|
||||
}
|
||||
b := f()
|
||||
b := f(encryption.StateEncryptionTODO())
|
||||
log.Printf("[TRACE] Meta.BackendForLocalPlan: instantiated backend of type %T", b)
|
||||
|
||||
schema := b.ConfigSchema()
|
||||
@ -371,7 +372,7 @@ func (m *Meta) BackendForLocalPlan(settings plans.Backend) (backend.Enhanced, tf
|
||||
return nil, diags
|
||||
}
|
||||
cliOpts.Validation = false // don't validate here in case config contains file(...) calls where the file doesn't exist
|
||||
local := backendLocal.NewWithBackend(b)
|
||||
local := backendLocal.NewWithBackend(b, encryption.StateEncryptionTODO())
|
||||
if err := local.CLIInit(cliOpts); err != nil {
|
||||
// Local backend should never fail, so this is always a bug.
|
||||
panic(err)
|
||||
@ -493,7 +494,7 @@ func (m *Meta) backendConfig(opts *BackendOpts) (*configs.Backend, int, tfdiags.
|
||||
})
|
||||
return nil, 0, diags
|
||||
}
|
||||
b := bf()
|
||||
b := bf(encryption.StateEncryptionTODO())
|
||||
|
||||
configSchema := b.ConfigSchema()
|
||||
configBody := c.Config
|
||||
@ -791,25 +792,25 @@ func (m *Meta) backendFromState(ctx context.Context) (backend.Backend, tfdiags.D
|
||||
if s == nil {
|
||||
// no state, so return a local backend
|
||||
log.Printf("[TRACE] Meta.Backend: backend has not previously been initialized in this working directory")
|
||||
return backendLocal.New(), diags
|
||||
return backendLocal.New(encryption.StateEncryptionTODO()), diags
|
||||
}
|
||||
if s.Backend == nil {
|
||||
// s.Backend is nil, so return a local backend
|
||||
log.Printf("[TRACE] Meta.Backend: working directory was previously initialized but has no backend (is using legacy remote state?)")
|
||||
return backendLocal.New(), diags
|
||||
return backendLocal.New(encryption.StateEncryptionTODO()), diags
|
||||
}
|
||||
log.Printf("[TRACE] Meta.Backend: working directory was previously initialized for %q backend", s.Backend.Type)
|
||||
|
||||
//backend init function
|
||||
if s.Backend.Type == "" {
|
||||
return backendLocal.New(), diags
|
||||
return backendLocal.New(encryption.StateEncryptionTODO()), diags
|
||||
}
|
||||
f := backendInit.Backend(s.Backend.Type)
|
||||
if f == nil {
|
||||
diags = diags.Append(fmt.Errorf(strings.TrimSpace(errBackendSavedUnknown), s.Backend.Type))
|
||||
return nil, diags
|
||||
}
|
||||
b := f()
|
||||
b := f(encryption.StateEncryptionTODO())
|
||||
|
||||
// The configuration saved in the working directory state file is used
|
||||
// in this case, since it will contain any additional values that
|
||||
@ -1266,7 +1267,7 @@ func (m *Meta) savedBackend(sMgr *clistate.LocalState) (backend.Backend, tfdiags
|
||||
diags = diags.Append(fmt.Errorf(strings.TrimSpace(errBackendSavedUnknown), s.Backend.Type))
|
||||
return nil, diags
|
||||
}
|
||||
b := f()
|
||||
b := f(encryption.StateEncryptionTODO())
|
||||
|
||||
// The configuration saved in the working directory state file is used
|
||||
// in this case, since it will contain any additional values that
|
||||
@ -1354,7 +1355,7 @@ func (m *Meta) backendConfigNeedsMigration(c *configs.Backend, s *legacy.Backend
|
||||
log.Printf("[TRACE] backendConfigNeedsMigration: no backend of type %q, which migration codepath must handle", c.Type)
|
||||
return true // let the migration codepath deal with the missing backend
|
||||
}
|
||||
b := f()
|
||||
b := f(encryption.StateEncryptionTODO())
|
||||
|
||||
schema := b.ConfigSchema()
|
||||
decSpec := schema.NoneRequired().DecoderSpec()
|
||||
@ -1391,7 +1392,7 @@ func (m *Meta) backendInitFromConfig(c *configs.Backend) (backend.Backend, cty.V
|
||||
diags = diags.Append(fmt.Errorf(strings.TrimSpace(errBackendNewUnknown), c.Type))
|
||||
return nil, cty.NilVal, diags
|
||||
}
|
||||
b := f()
|
||||
b := f(encryption.StateEncryptionTODO())
|
||||
|
||||
schema := b.ConfigSchema()
|
||||
decSpec := schema.NoneRequired().DecoderSpec()
|
||||
|
@ -22,6 +22,7 @@ import (
|
||||
"github.com/opentofu/opentofu/internal/command/arguments"
|
||||
"github.com/opentofu/opentofu/internal/command/clistate"
|
||||
"github.com/opentofu/opentofu/internal/command/views"
|
||||
"github.com/opentofu/opentofu/internal/encryption"
|
||||
"github.com/opentofu/opentofu/internal/states"
|
||||
"github.com/opentofu/opentofu/internal/states/statemgr"
|
||||
"github.com/opentofu/opentofu/internal/tofu"
|
||||
@ -497,7 +498,7 @@ func (m *Meta) backendMigrateNonEmptyConfirm(
|
||||
|
||||
// Helper to write the state
|
||||
saveHelper := func(n, path string, s *states.State) error {
|
||||
return statemgr.WriteAndPersist(statemgr.NewFilesystem(path), s, nil)
|
||||
return statemgr.WriteAndPersist(statemgr.NewFilesystem(path, encryption.StateEncryptionDisabled()), s, nil)
|
||||
}
|
||||
|
||||
// Write the states
|
||||
|
@ -21,6 +21,7 @@ import (
|
||||
"github.com/opentofu/opentofu/internal/backend"
|
||||
"github.com/opentofu/opentofu/internal/configs"
|
||||
"github.com/opentofu/opentofu/internal/copy"
|
||||
"github.com/opentofu/opentofu/internal/encryption"
|
||||
"github.com/opentofu/opentofu/internal/plans"
|
||||
"github.com/opentofu/opentofu/internal/states"
|
||||
"github.com/opentofu/opentofu/internal/states/statefile"
|
||||
@ -281,7 +282,7 @@ func TestMetaBackend_configureNew(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
actual, err := statefile.Read(f)
|
||||
actual, err := statefile.Read(f, encryption.StateEncryptionDisabled())
|
||||
f.Close()
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
@ -355,7 +356,7 @@ func TestMetaBackend_configureNewWithState(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
actual, err := statefile.Read(f)
|
||||
actual, err := statefile.Read(f, encryption.StateEncryptionDisabled())
|
||||
f.Close()
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
@ -404,7 +405,7 @@ func TestMetaBackend_configureNewWithoutCopy(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
actual, err := statefile.Read(f)
|
||||
actual, err := statefile.Read(f, encryption.StateEncryptionDisabled())
|
||||
f.Close()
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
@ -521,7 +522,7 @@ func TestMetaBackend_configureNewWithStateExisting(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
actual, err := statefile.Read(f)
|
||||
actual, err := statefile.Read(f, encryption.StateEncryptionDisabled())
|
||||
f.Close()
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
@ -592,7 +593,7 @@ func TestMetaBackend_configureNewWithStateExistingNoMigrate(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
actual, err := statefile.Read(f)
|
||||
actual, err := statefile.Read(f, encryption.StateEncryptionDisabled())
|
||||
f.Close()
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
@ -711,7 +712,7 @@ func TestMetaBackend_configuredChange(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
actual, err := statefile.Read(f)
|
||||
actual, err := statefile.Read(f, encryption.StateEncryptionDisabled())
|
||||
f.Close()
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
@ -773,7 +774,7 @@ func TestMetaBackend_reconfigureChange(t *testing.T) {
|
||||
}
|
||||
|
||||
// verify that the old state is still there
|
||||
s = statemgr.NewFilesystem("local-state.tfstate")
|
||||
s = statemgr.NewFilesystem("local-state.tfstate", encryption.StateEncryptionDisabled())
|
||||
if err := s.RefreshState(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -1601,7 +1602,7 @@ func TestMetaBackend_planLocal(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
actual, err := statefile.Read(f)
|
||||
actual, err := statefile.Read(f, encryption.StateEncryptionDisabled())
|
||||
f.Close()
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
@ -1643,7 +1644,7 @@ func TestMetaBackend_planLocalStatePath(t *testing.T) {
|
||||
statePath := "foo.tfstate"
|
||||
|
||||
// put an initial state there that needs to be backed up
|
||||
err = statemgr.WriteAndPersist(statemgr.NewFilesystem(statePath), original, nil)
|
||||
err = statemgr.WriteAndPersist(statemgr.NewFilesystem(statePath, encryption.StateEncryptionDisabled()), original, nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -1702,7 +1703,7 @@ func TestMetaBackend_planLocalStatePath(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
actual, err := statefile.Read(f)
|
||||
actual, err := statefile.Read(f, encryption.StateEncryptionDisabled())
|
||||
f.Close()
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
@ -1789,7 +1790,7 @@ func TestMetaBackend_planLocalMatch(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
actual, err := statefile.Read(f)
|
||||
actual, err := statefile.Read(f, encryption.StateEncryptionDisabled())
|
||||
f.Close()
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
|
@ -24,6 +24,7 @@ import (
|
||||
backendinit "github.com/opentofu/opentofu/internal/backend/init"
|
||||
"github.com/opentofu/opentofu/internal/checks"
|
||||
"github.com/opentofu/opentofu/internal/configs/configschema"
|
||||
"github.com/opentofu/opentofu/internal/encryption"
|
||||
"github.com/opentofu/opentofu/internal/plans"
|
||||
"github.com/opentofu/opentofu/internal/providers"
|
||||
"github.com/opentofu/opentofu/internal/states"
|
||||
@ -479,7 +480,7 @@ func TestPlan_outBackend(t *testing.T) {
|
||||
t.Errorf("wrong backend workspace %q; want %q", got, want)
|
||||
}
|
||||
{
|
||||
httpBackend := backendinit.Backend("http")()
|
||||
httpBackend := backendinit.Backend("http")(encryption.StateEncryptionDisabled())
|
||||
schema := httpBackend.ConfigSchema()
|
||||
got, err := plan.Backend.Config.Decode(schema.ImpliedType())
|
||||
if err != nil {
|
||||
|
@ -22,6 +22,7 @@ import (
|
||||
|
||||
"github.com/opentofu/opentofu/internal/addrs"
|
||||
"github.com/opentofu/opentofu/internal/configs/configschema"
|
||||
"github.com/opentofu/opentofu/internal/encryption"
|
||||
"github.com/opentofu/opentofu/internal/providers"
|
||||
"github.com/opentofu/opentofu/internal/states"
|
||||
"github.com/opentofu/opentofu/internal/states/statefile"
|
||||
@ -75,7 +76,7 @@ func TestRefresh(t *testing.T) {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
|
||||
newStateFile, err := statefile.Read(f)
|
||||
newStateFile, err := statefile.Read(f, encryption.StateEncryptionDisabled())
|
||||
f.Close()
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
@ -218,7 +219,7 @@ func TestRefresh_cwd(t *testing.T) {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
|
||||
newStateFile, err := statefile.Read(f)
|
||||
newStateFile, err := statefile.Read(f, encryption.StateEncryptionDisabled())
|
||||
f.Close()
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
@ -243,7 +244,7 @@ func TestRefresh_defaultState(t *testing.T) {
|
||||
// default filename.
|
||||
statePath := testStateFile(t, originalState)
|
||||
|
||||
localState := statemgr.NewFilesystem(statePath)
|
||||
localState := statemgr.NewFilesystem(statePath, encryption.StateEncryptionDisabled())
|
||||
if err := localState.RefreshState(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -569,7 +570,7 @@ func TestRefresh_backup(t *testing.T) {
|
||||
|
||||
// Need to put some state content in the output file so that there's
|
||||
// something to back up.
|
||||
err = statefile.Write(statefile.New(state, "baz", 0), outf)
|
||||
err = statefile.Write(statefile.New(state, "baz", 0), outf, encryption.StateEncryptionDisabled())
|
||||
if err != nil {
|
||||
t.Fatalf("error writing initial output state file %s", err)
|
||||
}
|
||||
|
@ -339,7 +339,7 @@ func getStateFromPath(path string) (*statefile.File, error) {
|
||||
defer file.Close()
|
||||
|
||||
var stateFile *statefile.File
|
||||
stateFile, err = statefile.Read(file)
|
||||
stateFile, err = statefile.Read(file, encryption.StateEncryptionTODO()) // Should we use encryption -> statefile config here?
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Error reading %s as a statefile: %w", path, err)
|
||||
}
|
||||
|
@ -11,6 +11,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/opentofu/opentofu/internal/addrs"
|
||||
"github.com/opentofu/opentofu/internal/encryption"
|
||||
"github.com/opentofu/opentofu/internal/states"
|
||||
"github.com/opentofu/opentofu/internal/states/statemgr"
|
||||
"github.com/opentofu/opentofu/internal/tfdiags"
|
||||
@ -34,7 +35,7 @@ func (c *StateMeta) State() (statemgr.Full, error) {
|
||||
|
||||
// use the specified state
|
||||
if c.statePath != "" {
|
||||
realState = statemgr.NewFilesystem(c.statePath)
|
||||
realState = statemgr.NewFilesystem(c.statePath, encryption.StateEncryptionTODO())
|
||||
} else {
|
||||
// Load the backend
|
||||
b, backendDiags := c.Backend(nil)
|
||||
|
@ -10,6 +10,7 @@ import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/opentofu/opentofu/internal/encryption"
|
||||
"github.com/opentofu/opentofu/internal/states/statefile"
|
||||
"github.com/opentofu/opentofu/internal/states/statemgr"
|
||||
)
|
||||
@ -64,7 +65,7 @@ func (c *StatePullCommand) Run(args []string) int {
|
||||
|
||||
if stateFile != nil { // we produce no output if the statefile is nil
|
||||
var buf bytes.Buffer
|
||||
err = statefile.Write(stateFile, &buf)
|
||||
err = statefile.Write(stateFile, &buf, encryption.StateEncryptionTODO())
|
||||
if err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Failed to write state: %s", err))
|
||||
return 1
|
||||
|
@ -16,6 +16,7 @@ import (
|
||||
"github.com/opentofu/opentofu/internal/command/arguments"
|
||||
"github.com/opentofu/opentofu/internal/command/clistate"
|
||||
"github.com/opentofu/opentofu/internal/command/views"
|
||||
"github.com/opentofu/opentofu/internal/encryption"
|
||||
"github.com/opentofu/opentofu/internal/states/statefile"
|
||||
"github.com/opentofu/opentofu/internal/states/statemgr"
|
||||
"github.com/opentofu/opentofu/internal/tfdiags"
|
||||
@ -68,7 +69,7 @@ func (c *StatePushCommand) Run(args []string) int {
|
||||
}
|
||||
|
||||
// Read the state
|
||||
srcStateFile, err := statefile.Read(r)
|
||||
srcStateFile, err := statefile.Read(r, encryption.StateEncryptionTODO()) // Should we use encryption -> statefile config here?
|
||||
if c, ok := r.(io.Closer); ok {
|
||||
// Close the reader if possible right now since we're done with it.
|
||||
c.Close()
|
||||
|
@ -13,6 +13,7 @@ import (
|
||||
"github.com/mitchellh/cli"
|
||||
"github.com/opentofu/opentofu/internal/backend"
|
||||
"github.com/opentofu/opentofu/internal/backend/remote-state/inmem"
|
||||
"github.com/opentofu/opentofu/internal/encryption"
|
||||
"github.com/opentofu/opentofu/internal/states"
|
||||
)
|
||||
|
||||
@ -264,7 +265,7 @@ func TestStatePush_forceRemoteState(t *testing.T) {
|
||||
}
|
||||
|
||||
// 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(encryption.StateEncryptionDisabled()), nil)
|
||||
sMgr, err := b.StateMgr("test")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
|
@ -17,6 +17,7 @@ import (
|
||||
"github.com/opentofu/opentofu/internal/command/jsonplan"
|
||||
"github.com/opentofu/opentofu/internal/command/jsonprovider"
|
||||
"github.com/opentofu/opentofu/internal/command/views/json"
|
||||
"github.com/opentofu/opentofu/internal/encryption"
|
||||
"github.com/opentofu/opentofu/internal/plans"
|
||||
"github.com/opentofu/opentofu/internal/states/statefile"
|
||||
"github.com/opentofu/opentofu/internal/tfdiags"
|
||||
@ -29,7 +30,7 @@ type Operation interface {
|
||||
Stopping()
|
||||
Cancelled(planMode plans.Mode)
|
||||
|
||||
EmergencyDumpState(stateFile *statefile.File) error
|
||||
EmergencyDumpState(stateFile *statefile.File, enc encryption.StateEncryption) error
|
||||
|
||||
PlannedChange(change *plans.ResourceInstanceChangeSrc)
|
||||
Plan(plan *plans.Plan, schemas *tofu.Schemas)
|
||||
@ -83,9 +84,9 @@ func (v *OperationHuman) Cancelled(planMode plans.Mode) {
|
||||
}
|
||||
}
|
||||
|
||||
func (v *OperationHuman) EmergencyDumpState(stateFile *statefile.File) error {
|
||||
func (v *OperationHuman) EmergencyDumpState(stateFile *statefile.File, enc encryption.StateEncryption) error {
|
||||
stateBuf := new(bytes.Buffer)
|
||||
jsonErr := statefile.Write(stateFile, stateBuf)
|
||||
jsonErr := statefile.Write(stateFile, stateBuf, enc)
|
||||
if jsonErr != nil {
|
||||
return jsonErr
|
||||
}
|
||||
@ -199,9 +200,9 @@ func (v *OperationJSON) Cancelled(planMode plans.Mode) {
|
||||
}
|
||||
}
|
||||
|
||||
func (v *OperationJSON) EmergencyDumpState(stateFile *statefile.File) error {
|
||||
func (v *OperationJSON) EmergencyDumpState(stateFile *statefile.File, enc encryption.StateEncryption) error {
|
||||
stateBuf := new(bytes.Buffer)
|
||||
jsonErr := statefile.Write(stateFile, stateBuf)
|
||||
jsonErr := statefile.Write(stateFile, stateBuf, enc)
|
||||
if jsonErr != nil {
|
||||
return jsonErr
|
||||
}
|
||||
|
@ -13,6 +13,7 @@ import (
|
||||
|
||||
"github.com/opentofu/opentofu/internal/addrs"
|
||||
"github.com/opentofu/opentofu/internal/command/arguments"
|
||||
"github.com/opentofu/opentofu/internal/encryption"
|
||||
"github.com/opentofu/opentofu/internal/lang/globalref"
|
||||
"github.com/opentofu/opentofu/internal/plans"
|
||||
"github.com/opentofu/opentofu/internal/states"
|
||||
@ -67,7 +68,7 @@ func TestOperation_emergencyDumpState(t *testing.T) {
|
||||
|
||||
stateFile := statefile.New(nil, "foo", 1)
|
||||
|
||||
err := v.EmergencyDumpState(stateFile)
|
||||
err := v.EmergencyDumpState(stateFile, encryption.StateEncryptionDisabled())
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error dumping state: %s", err)
|
||||
}
|
||||
@ -532,7 +533,7 @@ func TestOperationJSON_emergencyDumpState(t *testing.T) {
|
||||
|
||||
stateFile := statefile.New(nil, "foo", 1)
|
||||
stateBuf := new(bytes.Buffer)
|
||||
err := statefile.Write(stateFile, stateBuf)
|
||||
err := statefile.Write(stateFile, stateBuf, encryption.StateEncryptionDisabled())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -542,7 +543,7 @@ func TestOperationJSON_emergencyDumpState(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
err = v.EmergencyDumpState(stateFile)
|
||||
err = v.EmergencyDumpState(stateFile, encryption.StateEncryptionDisabled())
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error dumping state: %s", err)
|
||||
}
|
||||
|
@ -16,6 +16,7 @@ import (
|
||||
"github.com/opentofu/opentofu/internal/backend"
|
||||
"github.com/opentofu/opentofu/internal/backend/local"
|
||||
"github.com/opentofu/opentofu/internal/backend/remote-state/inmem"
|
||||
"github.com/opentofu/opentofu/internal/encryption"
|
||||
"github.com/opentofu/opentofu/internal/states"
|
||||
"github.com/opentofu/opentofu/internal/states/statemgr"
|
||||
|
||||
@ -253,7 +254,7 @@ func TestWorkspace_createWithState(t *testing.T) {
|
||||
)
|
||||
})
|
||||
|
||||
err := statemgr.WriteAndPersist(statemgr.NewFilesystem("test.tfstate"), originalState, nil)
|
||||
err := statemgr.WriteAndPersist(statemgr.NewFilesystem("test.tfstate", encryption.StateEncryptionDisabled()), originalState, nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -270,13 +271,13 @@ func TestWorkspace_createWithState(t *testing.T) {
|
||||
}
|
||||
|
||||
newPath := filepath.Join(local.DefaultWorkspaceDir, "test", DefaultStateFilename)
|
||||
envState := statemgr.NewFilesystem(newPath)
|
||||
envState := statemgr.NewFilesystem(newPath, encryption.StateEncryptionDisabled())
|
||||
err = envState.RefreshState()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
b := backend.TestBackendConfig(t, inmem.New(), nil)
|
||||
b := backend.TestBackendConfig(t, inmem.New(encryption.StateEncryptionDisabled()), nil)
|
||||
sMgr, err := b.StateMgr(workspace)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
|
@ -17,6 +17,7 @@ import (
|
||||
"github.com/opentofu/opentofu/internal/command/arguments"
|
||||
"github.com/opentofu/opentofu/internal/command/clistate"
|
||||
"github.com/opentofu/opentofu/internal/command/views"
|
||||
"github.com/opentofu/opentofu/internal/encryption"
|
||||
"github.com/opentofu/opentofu/internal/states/statefile"
|
||||
"github.com/opentofu/opentofu/internal/tfdiags"
|
||||
)
|
||||
@ -150,7 +151,7 @@ func (c *WorkspaceNewCommand) Run(args []string) int {
|
||||
return 1
|
||||
}
|
||||
|
||||
stateFile, err := statefile.Read(f)
|
||||
stateFile, err := statefile.Read(f, encryption.StateEncryptionTODO()) // Should we use encryption -> statefile config here?
|
||||
if err != nil {
|
||||
c.Ui.Error(err.Error())
|
||||
return 1
|
||||
|
16
internal/configs/state_encryption.go
Normal file
16
internal/configs/state_encryption.go
Normal file
@ -0,0 +1,16 @@
|
||||
// Copyright (c) The OpenTofu Authors
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
// Copyright (c) 2023 HashiCorp, Inc.
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
package configs
|
||||
|
||||
import "github.com/hashicorp/hcl/v2"
|
||||
|
||||
type StateEncryption struct {
|
||||
Type string
|
||||
Config hcl.Body
|
||||
|
||||
TypeRange hcl.Range
|
||||
DeclRange hcl.Range
|
||||
}
|
@ -193,7 +193,7 @@ func (b *binary) StateFromFile(filename string) (*states.State, error) {
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
stateFile, err := statefile.Read(f)
|
||||
stateFile, err := statefile.Read(f, encryption.StateEncryptionDisabled())
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Error reading statefile: %w", err)
|
||||
}
|
||||
@ -231,7 +231,7 @@ func (b *binary) SetLocalState(state *states.State) error {
|
||||
Lineage: "fake-for-testing",
|
||||
State: state,
|
||||
}
|
||||
return statefile.Write(sf, f)
|
||||
return statefile.Write(sf, f, encryption.StateEncryptionDisabled())
|
||||
}
|
||||
|
||||
func GoBuild(pkgPath, tmpPrefix string) string {
|
||||
|
@ -90,3 +90,21 @@ func (s *stateEncryption) DecryptState(encryptedState []byte) ([]byte, error) {
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func StateEncryptionDisabled() StateEncryption {
|
||||
return &stateDisabled{}
|
||||
}
|
||||
|
||||
type stateDisabled struct{}
|
||||
|
||||
func (s *stateDisabled) EncryptState(plainState []byte) ([]byte, error) {
|
||||
return plainState, nil
|
||||
}
|
||||
func (s *stateDisabled) DecryptState(encryptedState []byte) ([]byte, error) {
|
||||
return encryptedState, nil
|
||||
}
|
||||
|
||||
// TODO REMOVEME once state encryption is fully integrated into the codebase
|
||||
func StateEncryptionTODO() StateEncryption {
|
||||
return &stateDisabled{}
|
||||
}
|
||||
|
@ -170,7 +170,7 @@ func (r *Reader) ReadStateFile() (*statefile.File, error) {
|
||||
if err != nil {
|
||||
return nil, errUnusable(fmt.Errorf("failed to extract state from plan file: %w", err))
|
||||
}
|
||||
return statefile.Read(r)
|
||||
return statefile.Read(r, encryption.StateEncryptionDisabled())
|
||||
}
|
||||
}
|
||||
return nil, errUnusable(statefile.ErrNoState)
|
||||
@ -188,7 +188,7 @@ func (r *Reader) ReadPrevStateFile() (*statefile.File, error) {
|
||||
if err != nil {
|
||||
return nil, errUnusable(fmt.Errorf("failed to extract previous state from plan file: %w", err))
|
||||
}
|
||||
return statefile.Read(r)
|
||||
return statefile.Read(r, encryption.StateEncryptionDisabled())
|
||||
}
|
||||
}
|
||||
return nil, errUnusable(statefile.ErrNoState)
|
||||
|
@ -85,7 +85,7 @@ func Create(filename string, args CreateArgs, enc encryption.PlanEncryption) err
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create embedded tfstate file: %w", err)
|
||||
}
|
||||
err = statefile.Write(args.StateFile, w)
|
||||
err = statefile.Write(args.StateFile, w, encryption.StateEncryptionDisabled())
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to write state snapshot: %w", err)
|
||||
}
|
||||
@ -101,7 +101,7 @@ func Create(filename string, args CreateArgs, enc encryption.PlanEncryption) err
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create embedded tfstate-prev file: %w", err)
|
||||
}
|
||||
err = statefile.Write(args.PreviousRunStateFile, w)
|
||||
err = statefile.Write(args.PreviousRunStateFile, w, encryption.StateEncryptionDisabled())
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to write previous state snapshot: %w", err)
|
||||
}
|
||||
|
@ -14,6 +14,7 @@ import (
|
||||
uuid "github.com/hashicorp/go-uuid"
|
||||
|
||||
"github.com/opentofu/opentofu/internal/backend/local"
|
||||
"github.com/opentofu/opentofu/internal/encryption"
|
||||
"github.com/opentofu/opentofu/internal/states"
|
||||
"github.com/opentofu/opentofu/internal/states/statefile"
|
||||
"github.com/opentofu/opentofu/internal/states/statemgr"
|
||||
@ -29,6 +30,8 @@ type State struct {
|
||||
|
||||
Client Client
|
||||
|
||||
encryption encryption.StateEncryption
|
||||
|
||||
// We track two pieces of meta data in addition to the state itself:
|
||||
//
|
||||
// lineage - the state's unique ID
|
||||
@ -47,13 +50,24 @@ type State struct {
|
||||
// state snapshots created while a OpenTofu Core apply operation is in
|
||||
// progress. Otherwise (by default) it will accept persistent snapshots
|
||||
// using the default rules defined in the local backend.
|
||||
DisableIntermediateSnapshots bool
|
||||
disableIntermediateSnapshots bool
|
||||
}
|
||||
|
||||
var _ statemgr.Full = (*State)(nil)
|
||||
var _ statemgr.Migrator = (*State)(nil)
|
||||
var _ local.IntermediateStateConditionalPersister = (*State)(nil)
|
||||
|
||||
func NewState(client Client, enc encryption.StateEncryption) *State {
|
||||
return &State{
|
||||
Client: client,
|
||||
encryption: enc,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *State) DisableIntermediateSnapshots() {
|
||||
s.disableIntermediateSnapshots = true
|
||||
}
|
||||
|
||||
// statemgr.Reader impl.
|
||||
func (s *State) State() *states.State {
|
||||
s.mu.Lock()
|
||||
@ -150,7 +164,7 @@ func (s *State) refreshState() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
stateFile, err := statefile.Read(bytes.NewReader(payload.Data))
|
||||
stateFile, err := statefile.Read(bytes.NewReader(payload.Data), s.encryption)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -207,7 +221,7 @@ func (s *State) PersistState(schemas *tofu.Schemas) error {
|
||||
f := statefile.New(s.state, s.lineage, s.serial)
|
||||
|
||||
var buf bytes.Buffer
|
||||
err := statefile.Write(f, &buf)
|
||||
err := statefile.Write(f, &buf, s.encryption)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -231,7 +245,7 @@ func (s *State) PersistState(schemas *tofu.Schemas) error {
|
||||
|
||||
// ShouldPersistIntermediateState implements local.IntermediateStateConditionalPersister
|
||||
func (s *State) ShouldPersistIntermediateState(info *local.IntermediateStatePersistInfo) bool {
|
||||
if s.DisableIntermediateSnapshots {
|
||||
if s.disableIntermediateSnapshots {
|
||||
return false
|
||||
}
|
||||
return local.DefaultIntermediateStatePersistRule(info)
|
||||
|
@ -15,6 +15,7 @@ import (
|
||||
"github.com/zclconf/go-cty/cty"
|
||||
|
||||
"github.com/opentofu/opentofu/internal/addrs"
|
||||
"github.com/opentofu/opentofu/internal/encryption"
|
||||
"github.com/opentofu/opentofu/internal/states"
|
||||
"github.com/opentofu/opentofu/internal/states/statefile"
|
||||
"github.com/opentofu/opentofu/internal/states/statemgr"
|
||||
@ -32,9 +33,7 @@ func TestState_impl(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestStateRace(t *testing.T) {
|
||||
s := &State{
|
||||
Client: nilClient{},
|
||||
}
|
||||
s := NewState(nilClient{}, encryption.StateEncryptionDisabled())
|
||||
|
||||
current := states.NewState()
|
||||
|
||||
@ -327,9 +326,10 @@ func TestStatePersist(t *testing.T) {
|
||||
// Initial setup of state just to give us a fixed starting point for our
|
||||
// test assertions below, or else we'd need to deal with
|
||||
// random lineage.
|
||||
mgr := &State{
|
||||
Client: &mockClient{},
|
||||
}
|
||||
mgr := NewState(
|
||||
&mockClient{},
|
||||
encryption.StateEncryptionDisabled(),
|
||||
)
|
||||
|
||||
// In normal use (during a OpenTofu operation) we always refresh and read
|
||||
// before any writes would happen, so we'll mimic that here for realism.
|
||||
@ -389,8 +389,8 @@ func TestStatePersist(t *testing.T) {
|
||||
|
||||
func TestState_GetRootOutputValues(t *testing.T) {
|
||||
// Initial setup of state with outputs already defined
|
||||
mgr := &State{
|
||||
Client: &mockClient{
|
||||
mgr := NewState(
|
||||
&mockClient{
|
||||
current: []byte(`
|
||||
{
|
||||
"version": 4,
|
||||
@ -402,7 +402,8 @@ func TestState_GetRootOutputValues(t *testing.T) {
|
||||
}
|
||||
`),
|
||||
},
|
||||
}
|
||||
encryption.StateEncryptionDisabled(),
|
||||
)
|
||||
|
||||
outputs, err := mgr.GetRootOutputValues()
|
||||
if err != nil {
|
||||
@ -427,8 +428,8 @@ type migrationTestCase struct {
|
||||
}
|
||||
|
||||
func TestWriteStateForMigration(t *testing.T) {
|
||||
mgr := &State{
|
||||
Client: &mockClient{
|
||||
mgr := NewState(
|
||||
&mockClient{
|
||||
current: []byte(`
|
||||
{
|
||||
"version": 4,
|
||||
@ -440,7 +441,8 @@ func TestWriteStateForMigration(t *testing.T) {
|
||||
}
|
||||
`),
|
||||
},
|
||||
}
|
||||
encryption.StateEncryptionDisabled(),
|
||||
)
|
||||
|
||||
testCases := []migrationTestCase{
|
||||
// Refreshing state before we run the test loop causes a GET
|
||||
@ -583,8 +585,8 @@ func TestWriteStateForMigration(t *testing.T) {
|
||||
// us to test that -force continues to work for backends without
|
||||
// this interface, but that this interface works for those that do.
|
||||
func TestWriteStateForMigrationWithForcePushClient(t *testing.T) {
|
||||
mgr := &State{
|
||||
Client: &mockClientForcePusher{
|
||||
mgr := NewState(
|
||||
&mockClientForcePusher{
|
||||
current: []byte(`
|
||||
{
|
||||
"version": 4,
|
||||
@ -596,7 +598,8 @@ func TestWriteStateForMigrationWithForcePushClient(t *testing.T) {
|
||||
}
|
||||
`),
|
||||
},
|
||||
}
|
||||
encryption.StateEncryptionDisabled(),
|
||||
)
|
||||
|
||||
testCases := []migrationTestCase{
|
||||
// Refreshing state before we run the test loop causes a GET
|
||||
|
@ -9,6 +9,7 @@ import (
|
||||
"bytes"
|
||||
"testing"
|
||||
|
||||
"github.com/opentofu/opentofu/internal/encryption"
|
||||
"github.com/opentofu/opentofu/internal/states/statefile"
|
||||
"github.com/opentofu/opentofu/internal/states/statemgr"
|
||||
)
|
||||
@ -18,7 +19,7 @@ func TestClient(t *testing.T, c Client) {
|
||||
var buf bytes.Buffer
|
||||
s := statemgr.TestFullInitialState()
|
||||
sf := statefile.New(s, "stub-lineage", 2)
|
||||
err := statefile.Write(sf, &buf)
|
||||
err := statefile.Write(sf, &buf, encryption.StateEncryptionDisabled())
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ package statefile
|
||||
import (
|
||||
"bytes"
|
||||
|
||||
"github.com/opentofu/opentofu/internal/encryption"
|
||||
"github.com/opentofu/opentofu/internal/states"
|
||||
)
|
||||
|
||||
@ -30,12 +31,12 @@ func StatesMarshalEqual(a, b *states.State) bool {
|
||||
// We write here some temporary files that have no header information
|
||||
// populated, thus ensuring that we're only comparing the state itself
|
||||
// and not any metadata.
|
||||
err := Write(&File{State: a}, &aBuf)
|
||||
err := Write(&File{State: a}, &aBuf, encryption.StateEncryptionDisabled())
|
||||
if err != nil {
|
||||
// Should never happen, because we're writing to an in-memory buffer
|
||||
panic(err)
|
||||
}
|
||||
err = Write(&File{State: b}, &bBuf)
|
||||
err = Write(&File{State: b}, &bBuf, encryption.StateEncryptionDisabled())
|
||||
if err != nil {
|
||||
// Should never happen, because we're writing to an in-memory buffer
|
||||
panic(err)
|
||||
|
@ -14,6 +14,7 @@ import (
|
||||
|
||||
version "github.com/hashicorp/go-version"
|
||||
|
||||
"github.com/opentofu/opentofu/internal/encryption"
|
||||
"github.com/opentofu/opentofu/internal/tfdiags"
|
||||
tfversion "github.com/opentofu/opentofu/version"
|
||||
)
|
||||
@ -49,7 +50,7 @@ func (e *ErrUnusableState) Unwrap() error {
|
||||
// If the state file is empty, the special error value ErrNoState is returned.
|
||||
// Otherwise, the returned error might be a wrapper around tfdiags.Diagnostics
|
||||
// potentially describing multiple errors.
|
||||
func Read(r io.Reader) (*File, error) {
|
||||
func Read(r io.Reader, enc encryption.StateEncryption) (*File, error) {
|
||||
// Some callers provide us a "typed nil" *os.File here, which would
|
||||
// cause us to panic below if we tried to use it.
|
||||
if f, ok := r.(*os.File); ok && f == nil {
|
||||
@ -75,7 +76,10 @@ func Read(r io.Reader) (*File, error) {
|
||||
return nil, ErrNoState
|
||||
}
|
||||
|
||||
state, err := readState(src)
|
||||
decrypted, decDiags := enc.DecryptState(src)
|
||||
diags = diags.Append(decDiags)
|
||||
|
||||
state, err := readState(decrypted)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -6,6 +6,8 @@ import (
|
||||
"errors"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/opentofu/opentofu/internal/encryption"
|
||||
)
|
||||
|
||||
func TestReadErrNoState_emptyFile(t *testing.T) {
|
||||
@ -15,7 +17,7 @@ func TestReadErrNoState_emptyFile(t *testing.T) {
|
||||
}
|
||||
defer emptyFile.Close()
|
||||
|
||||
_, err = Read(emptyFile)
|
||||
_, err = Read(emptyFile, encryption.StateEncryptionDisabled())
|
||||
if !errors.Is(err, ErrNoState) {
|
||||
t.Fatalf("expected ErrNoState, got %T", err)
|
||||
}
|
||||
@ -27,7 +29,7 @@ func TestReadErrNoState_nilFile(t *testing.T) {
|
||||
t.Fatal("wrongly succeeded in opening non-existent file")
|
||||
}
|
||||
|
||||
_, err = Read(nilFile)
|
||||
_, err = Read(nilFile, encryption.StateEncryptionDisabled())
|
||||
if !errors.Is(err, ErrNoState) {
|
||||
t.Fatalf("expected ErrNoState, got %T", err)
|
||||
}
|
||||
|
@ -14,6 +14,7 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/go-test/deep"
|
||||
"github.com/opentofu/opentofu/internal/encryption"
|
||||
)
|
||||
|
||||
func TestRoundtrip(t *testing.T) {
|
||||
@ -53,13 +54,13 @@ func TestRoundtrip(t *testing.T) {
|
||||
}
|
||||
defer ir.Close()
|
||||
|
||||
f, err := Read(ir)
|
||||
f, err := Read(ir, encryption.StateEncryptionDisabled())
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
|
||||
var buf bytes.Buffer
|
||||
err = Write(f, &buf)
|
||||
err = Write(f, &buf, encryption.StateEncryptionDisabled())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -17,6 +17,7 @@ import (
|
||||
|
||||
"github.com/opentofu/opentofu/internal/addrs"
|
||||
"github.com/opentofu/opentofu/internal/checks"
|
||||
"github.com/opentofu/opentofu/internal/encryption"
|
||||
"github.com/opentofu/opentofu/internal/lang/marks"
|
||||
"github.com/opentofu/opentofu/internal/states"
|
||||
"github.com/opentofu/opentofu/internal/tfdiags"
|
||||
@ -313,7 +314,7 @@ func prepareStateV4(sV4 *stateV4) (*File, tfdiags.Diagnostics) {
|
||||
return file, diags
|
||||
}
|
||||
|
||||
func writeStateV4(file *File, w io.Writer) tfdiags.Diagnostics {
|
||||
func writeStateV4(file *File, w io.Writer, enc encryption.StateEncryption) tfdiags.Diagnostics {
|
||||
// Here we'll convert back from the "File" representation to our
|
||||
// stateV4 struct representation and write that.
|
||||
//
|
||||
@ -435,7 +436,10 @@ func writeStateV4(file *File, w io.Writer) tfdiags.Diagnostics {
|
||||
}
|
||||
src = append(src, '\n')
|
||||
|
||||
_, err = w.Write(src)
|
||||
encrypted, encDiags := enc.EncryptState(src)
|
||||
diags = diags.Append(encDiags)
|
||||
|
||||
_, err = w.Write(encrypted)
|
||||
if err != nil {
|
||||
diags = diags.Append(tfdiags.Sourceless(
|
||||
tfdiags.Error,
|
||||
|
@ -8,16 +8,17 @@ package statefile
|
||||
import (
|
||||
"io"
|
||||
|
||||
"github.com/opentofu/opentofu/internal/encryption"
|
||||
tfversion "github.com/opentofu/opentofu/version"
|
||||
)
|
||||
|
||||
// Write writes the given state to the given writer in the current state
|
||||
// serialization format.
|
||||
func Write(s *File, w io.Writer) error {
|
||||
func Write(s *File, w io.Writer, enc encryption.StateEncryption) error {
|
||||
// Always record the current tofu version in the state.
|
||||
s.TerraformVersion = tfversion.SemVer
|
||||
|
||||
diags := writeStateV4(s, w)
|
||||
diags := writeStateV4(s, w, enc)
|
||||
return diags.Err()
|
||||
}
|
||||
|
||||
@ -26,6 +27,6 @@ func Write(s *File, w io.Writer) error {
|
||||
// intended for use in tests that need to override the current tofu
|
||||
// version.
|
||||
func WriteForTest(s *File, w io.Writer) error {
|
||||
diags := writeStateV4(s, w)
|
||||
diags := writeStateV4(s, w, encryption.StateEncryptionDisabled())
|
||||
return diags.Err()
|
||||
}
|
||||
|
@ -18,6 +18,7 @@ import (
|
||||
|
||||
multierror "github.com/hashicorp/go-multierror"
|
||||
|
||||
"github.com/opentofu/opentofu/internal/encryption"
|
||||
"github.com/opentofu/opentofu/internal/states"
|
||||
"github.com/opentofu/opentofu/internal/states/statefile"
|
||||
"github.com/opentofu/opentofu/internal/tofu"
|
||||
@ -62,6 +63,8 @@ type Filesystem struct {
|
||||
readFile *statefile.File
|
||||
backupFile *statefile.File
|
||||
writtenBackup bool
|
||||
|
||||
encryption encryption.StateEncryption
|
||||
}
|
||||
|
||||
var (
|
||||
@ -75,20 +78,22 @@ var (
|
||||
//
|
||||
// This is equivalent to calling NewFileSystemBetweenPaths with statePath as
|
||||
// both of the path arguments.
|
||||
func NewFilesystem(statePath string) *Filesystem {
|
||||
func NewFilesystem(statePath string, enc encryption.StateEncryption) *Filesystem {
|
||||
return &Filesystem{
|
||||
path: statePath,
|
||||
readPath: statePath,
|
||||
path: statePath,
|
||||
readPath: statePath,
|
||||
encryption: enc,
|
||||
}
|
||||
}
|
||||
|
||||
// NewFilesystemBetweenPaths creates a filesystem-based state manager that
|
||||
// reads an initial snapshot from readPath and then writes all new snapshots to
|
||||
// writePath.
|
||||
func NewFilesystemBetweenPaths(readPath, writePath string) *Filesystem {
|
||||
func NewFilesystemBetweenPaths(readPath, writePath string, enc encryption.StateEncryption) *Filesystem {
|
||||
return &Filesystem{
|
||||
path: writePath,
|
||||
readPath: readPath,
|
||||
path: writePath,
|
||||
readPath: readPath,
|
||||
encryption: enc,
|
||||
}
|
||||
}
|
||||
|
||||
@ -187,7 +192,7 @@ func (s *Filesystem) persistState(schemas *tofu.Schemas) error {
|
||||
}
|
||||
defer bfh.Close()
|
||||
|
||||
err = statefile.Write(s.backupFile, bfh)
|
||||
err = statefile.Write(s.backupFile, bfh, s.encryption)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to write to local state backup file: %w", err)
|
||||
}
|
||||
@ -231,7 +236,7 @@ func (s *Filesystem) persistState(schemas *tofu.Schemas) error {
|
||||
}
|
||||
|
||||
log.Printf("[TRACE] statemgr.Filesystem: writing snapshot at %s", s.path)
|
||||
if err := statefile.Write(s.file, s.stateFileOut); err != nil {
|
||||
if err := statefile.Write(s.file, s.stateFileOut, s.encryption); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -303,7 +308,7 @@ func (s *Filesystem) refreshState() error {
|
||||
reader = s.stateFileOut
|
||||
}
|
||||
|
||||
f, err := statefile.Read(reader)
|
||||
f, err := statefile.Read(reader, s.encryption)
|
||||
// if there's no state then a nil file is fine
|
||||
if err != nil {
|
||||
if err != statefile.ErrNoState {
|
||||
@ -492,7 +497,7 @@ func (s *Filesystem) createStateFiles() error {
|
||||
|
||||
// If the file already existed with content then that'll be the content
|
||||
// of our backup file if we write a change later.
|
||||
s.backupFile, err = statefile.Read(s.stateFileOut)
|
||||
s.backupFile, err = statefile.Read(s.stateFileOut, s.encryption)
|
||||
if err != nil {
|
||||
if err != statefile.ErrNoState {
|
||||
return err
|
||||
|
@ -18,6 +18,7 @@ import (
|
||||
"github.com/zclconf/go-cty/cty"
|
||||
|
||||
"github.com/opentofu/opentofu/internal/addrs"
|
||||
"github.com/opentofu/opentofu/internal/encryption"
|
||||
"github.com/opentofu/opentofu/internal/states"
|
||||
"github.com/opentofu/opentofu/internal/states/statefile"
|
||||
tfversion "github.com/opentofu/opentofu/version"
|
||||
@ -169,7 +170,7 @@ func TestFilesystem_backup(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
bf, err := statefile.Read(bfh)
|
||||
bf, err := statefile.Read(bfh, encryption.StateEncryptionDisabled())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -210,7 +211,7 @@ func TestFilesystem_backupAndReadPath(t *testing.T) {
|
||||
Serial: 0,
|
||||
TerraformVersion: version.Must(version.NewVersion("1.2.3")),
|
||||
State: outState,
|
||||
}, outFile)
|
||||
}, outFile, encryption.StateEncryptionDisabled())
|
||||
if err != nil {
|
||||
t.Fatalf("failed to write initial outfile state to %s: %s", outFile.Name(), err)
|
||||
}
|
||||
@ -232,14 +233,14 @@ func TestFilesystem_backupAndReadPath(t *testing.T) {
|
||||
Serial: 0,
|
||||
TerraformVersion: version.Must(version.NewVersion("1.2.3")),
|
||||
State: inState,
|
||||
}, inFile)
|
||||
}, inFile, encryption.StateEncryptionDisabled())
|
||||
if err != nil {
|
||||
t.Fatalf("failed to write initial infile state to %s: %s", inFile.Name(), err)
|
||||
}
|
||||
|
||||
backupPath := outFile.Name() + ".backup"
|
||||
|
||||
ls := NewFilesystemBetweenPaths(inFile.Name(), outFile.Name())
|
||||
ls := NewFilesystemBetweenPaths(inFile.Name(), outFile.Name(), encryption.StateEncryptionDisabled())
|
||||
ls.SetBackupPath(backupPath)
|
||||
|
||||
newState := states.BuildState(func(ss *states.SyncState) {
|
||||
@ -262,7 +263,7 @@ func TestFilesystem_backupAndReadPath(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
bf, err := statefile.Read(bfh)
|
||||
bf, err := statefile.Read(bfh, encryption.StateEncryptionDisabled())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -276,7 +277,7 @@ func TestFilesystem_backupAndReadPath(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
of, err := statefile.Read(ofh)
|
||||
of, err := statefile.Read(ofh, encryption.StateEncryptionDisabled())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -289,7 +290,7 @@ func TestFilesystem_backupAndReadPath(t *testing.T) {
|
||||
|
||||
func TestFilesystem_nonExist(t *testing.T) {
|
||||
defer testOverrideVersion(t, "1.2.3")()
|
||||
ls := NewFilesystem("ishouldntexist")
|
||||
ls := NewFilesystem("ishouldntexist", encryption.StateEncryptionDisabled())
|
||||
if err := ls.RefreshState(); err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
@ -356,13 +357,13 @@ func testFilesystem(t *testing.T) *Filesystem {
|
||||
Serial: 0,
|
||||
TerraformVersion: version.Must(version.NewVersion("1.2.3")),
|
||||
State: TestFullInitialState(),
|
||||
}, f)
|
||||
}, f, encryption.StateEncryptionDisabled())
|
||||
if err != nil {
|
||||
t.Fatalf("failed to write initial state to %s: %s", f.Name(), err)
|
||||
}
|
||||
f.Close()
|
||||
|
||||
ls := NewFilesystem(f.Name())
|
||||
ls := NewFilesystem(f.Name(), encryption.StateEncryptionDisabled())
|
||||
if err := ls.RefreshState(); err != nil {
|
||||
t.Fatalf("initial refresh failed: %s", err)
|
||||
}
|
||||
@ -383,13 +384,13 @@ func TestFilesystem_refreshWhileLocked(t *testing.T) {
|
||||
Serial: 0,
|
||||
TerraformVersion: version.Must(version.NewVersion("1.2.3")),
|
||||
State: TestFullInitialState(),
|
||||
}, f)
|
||||
}, f, encryption.StateEncryptionDisabled())
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
f.Close()
|
||||
|
||||
s := NewFilesystem(f.Name())
|
||||
s := NewFilesystem(f.Name(), encryption.StateEncryptionDisabled())
|
||||
defer os.Remove(s.path)
|
||||
|
||||
// lock first
|
||||
|
@ -5,6 +5,7 @@ import (
|
||||
"log"
|
||||
"os"
|
||||
|
||||
"github.com/opentofu/opentofu/internal/encryption"
|
||||
"github.com/opentofu/opentofu/internal/states/statemgr"
|
||||
)
|
||||
|
||||
@ -15,7 +16,7 @@ func main() {
|
||||
log.Fatal(os.Args[0], "statefile")
|
||||
}
|
||||
|
||||
s := statemgr.NewFilesystem(os.Args[1])
|
||||
s := statemgr.NewFilesystem(os.Args[1], encryption.StateEncryptionDisabled())
|
||||
|
||||
info := statemgr.NewLockInfo()
|
||||
info.Operation = "test"
|
||||
|
Loading…
Reference in New Issue
Block a user