Skip to content

Commit

Permalink
reduce special error handling to 'replace-provider'
Browse files Browse the repository at this point in the history
This seeks to further reduce the acceptance of `Error: Invalid legacy
provider address` errors to scenarios where tfmigrate is performing `state
replace-provider`.

This is inspired by code review feedback from @minamijoyo here:
#145 (comment)
  • Loading branch information
mdb committed Sep 2, 2023
1 parent 37e2834 commit 67ed675
Show file tree
Hide file tree
Showing 3 changed files with 17 additions and 5 deletions.
4 changes: 2 additions & 2 deletions tfmigrate/migrator.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ type Migrator interface {

// setupWorkDir is a common helper function to set up work dir and returns the
// current state and a switch back function.
func setupWorkDir(ctx context.Context, tf tfexec.TerraformCLI, workspace string, isBackendTerraformCloud bool, backendConfig []string) (*tfexec.State, func(), error) {
func setupWorkDir(ctx context.Context, tf tfexec.TerraformCLI, workspace string, isBackendTerraformCloud bool, backendConfig []string, ignoreLegacyStateInitErr bool) (*tfexec.State, func(), error) {
// check if terraform command is available.
version, err := tf.Version(ctx)
if err != nil {
Expand All @@ -40,7 +40,7 @@ func setupWorkDir(ctx context.Context, tf tfexec.TerraformCLI, workspace string,
log.Printf("[INFO] [migrator@%s] initialize work dir\n", tf.Dir())
err = tf.Init(ctx, "-input=false", "-no-color")
if err != nil {
if supportsStateReplaceProvider && strings.Contains(err.Error(), tfexec.AcceptableLegacyStateInitError) {
if supportsStateReplaceProvider && ignoreLegacyStateInitErr && strings.Contains(err.Error(), tfexec.AcceptableLegacyStateInitError) {
log.Printf("[INFO] [migrator@%s] ignoring error '%s' initilizing work dir; the error is expected when using Terraform %s with a legacy Terraform state\n", tf.Dir(), tfexec.AcceptableLegacyStateInitError, constraints)
} else {
return nil, nil, err
Expand Down
4 changes: 2 additions & 2 deletions tfmigrate/multi_state_migrator.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,14 +119,14 @@ func NewMultiStateMigrator(fromDir string, toDir string, fromWorkspace string, t
// the Migrator interface between a single and multi state migrator.
func (m *MultiStateMigrator) plan(ctx context.Context) (*tfexec.State, *tfexec.State, error) {
// setup fromDir.
fromCurrentState, fromSwitchBackToRemoteFunc, err := setupWorkDir(ctx, m.fromTf, m.fromWorkspace, m.o.IsBackendTerraformCloud, m.o.BackendConfig)
fromCurrentState, fromSwitchBackToRemoteFunc, err := setupWorkDir(ctx, m.fromTf, m.fromWorkspace, m.o.IsBackendTerraformCloud, m.o.BackendConfig, false)
if err != nil {
return nil, nil, err
}
// switch back it to remote on exit.
defer fromSwitchBackToRemoteFunc()
// setup toDir.
toCurrentState, toSwitchBackToRemoteFunc, err := setupWorkDir(ctx, m.toTf, m.toWorkspace, m.o.IsBackendTerraformCloud, m.o.BackendConfig)
toCurrentState, toSwitchBackToRemoteFunc, err := setupWorkDir(ctx, m.toTf, m.toWorkspace, m.o.IsBackendTerraformCloud, m.o.BackendConfig, false)
if err != nil {
return nil, nil, err
}
Expand Down
14 changes: 13 additions & 1 deletion tfmigrate/state_migrator.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,8 +104,20 @@ func NewStateMigrator(dir string, workspace string, actions []StateAction,
// We intentionally keep this method private as to not expose internal states and unify
// the Migrator interface between a single and multi state migrator.
func (m *StateMigrator) plan(ctx context.Context) (*tfexec.State, error) {
ignoreLegacyStateInitErr := false
for _, action := range m.actions {
// When invoking `state replace-provider`, it's necessary to first
// invoke `terraform init`. However, when using a non-legacy Terraform CLI
// against a legacy Terraform state, `terraform init` returns an error.
// In this scenario, we can (and must) safely ignore the error.
if _, ok := action.(*StateReplaceProviderAction); ok {
ignoreLegacyStateInitErr = true
break
}
}

// setup work dir.
currentState, switchBackToRemoteFunc, err := setupWorkDir(ctx, m.tf, m.workspace, m.o.IsBackendTerraformCloud, m.o.BackendConfig)
currentState, switchBackToRemoteFunc, err := setupWorkDir(ctx, m.tf, m.workspace, m.o.IsBackendTerraformCloud, m.o.BackendConfig, ignoreLegacyStateInitErr)
if err != nil {
return nil, err
}
Expand Down

0 comments on commit 67ed675

Please sign in to comment.