diff --git a/.changes/unreleased/BUG FIXES-20250606-110444.yaml b/.changes/unreleased/BUG FIXES-20250606-110444.yaml new file mode 100644 index 00000000..39b43da6 --- /dev/null +++ b/.changes/unreleased/BUG FIXES-20250606-110444.yaml @@ -0,0 +1,5 @@ +kind: BUG FIXES +body: 'helper/resource: Fixed bug with import state mode where prior test config is not used for `ConfigFile` or `ConfigDirectory`' +time: 2025-06-06T11:04:44.925152-04:00 +custom: + Issue: "516" diff --git a/helper/resource/importstate/import_block_in_config_directory_test.go b/helper/resource/importstate/import_block_in_config_directory_test.go index cf24a024..d298808e 100644 --- a/helper/resource/importstate/import_block_in_config_directory_test.go +++ b/helper/resource/importstate/import_block_in_config_directory_test.go @@ -38,7 +38,6 @@ func TestImportBlock_InConfigDirectory(t *testing.T) { ResourceName: "examplecloud_container.test", ImportState: true, ImportStateKind: r.ImportBlockWithID, - ConfigDirectory: config.StaticDirectory(`testdata/2`), }, }, }) diff --git a/helper/resource/importstate/import_block_in_config_file_test.go b/helper/resource/importstate/import_block_in_config_file_test.go index db762f2d..7cfa7e1d 100644 --- a/helper/resource/importstate/import_block_in_config_file_test.go +++ b/helper/resource/importstate/import_block_in_config_file_test.go @@ -38,7 +38,6 @@ func TestImportBlock_InConfigFile(t *testing.T) { ResourceName: "examplecloud_container.test", ImportState: true, ImportStateKind: r.ImportBlockWithID, - ConfigFile: config.StaticFile(`testdata/2/examplecloud_container.tf`), }, }, }) diff --git a/helper/resource/importstate/import_command_with_id_test.go b/helper/resource/importstate/import_command_with_id_test.go index 34e211b6..52e7731b 100644 --- a/helper/resource/importstate/import_command_with_id_test.go +++ b/helper/resource/importstate/import_command_with_id_test.go @@ -11,6 +11,7 @@ import ( "github.com/hashicorp/terraform-plugin-go/tfprotov6" "github.com/hashicorp/terraform-plugin-go/tftypes" + "github.com/hashicorp/terraform-plugin-testing/config" r "github.com/hashicorp/terraform-plugin-testing/helper/resource" "github.com/hashicorp/terraform-plugin-testing/internal/testing/testprovider" "github.com/hashicorp/terraform-plugin-testing/internal/testing/testsdk/datasource" @@ -197,6 +198,60 @@ func TestImportCommand_ImportStateVerify(t *testing.T) { }) } +func TestImportCommand_InConfigFile(t *testing.T) { + t.Parallel() + + r.UnitTest(t, r.TestCase{ + TerraformVersionChecks: []tfversion.TerraformVersionCheck{ + tfversion.SkipBelow(tfversion.Version1_0_0), // ProtoV6ProviderFactories + }, + ProtoV6ProviderFactories: map[string]func() (tfprotov6.ProviderServer, error){ + "examplecloud": providerserver.NewProviderServer(testprovider.Provider{ + Resources: map[string]testprovider.Resource{ + "examplecloud_container": examplecloudResource(), + }, + }), + }, + Steps: []r.TestStep{ + { + ConfigFile: config.StaticFile(`testdata/1/examplecloud_container.tf`), + }, + { + ResourceName: "examplecloud_container.test", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestImportCommand_InConfigDirectory(t *testing.T) { + t.Parallel() + + r.UnitTest(t, r.TestCase{ + TerraformVersionChecks: []tfversion.TerraformVersionCheck{ + tfversion.SkipBelow(tfversion.Version1_0_0), // ProtoV6ProviderFactories + }, + ProtoV6ProviderFactories: map[string]func() (tfprotov6.ProviderServer, error){ + "examplecloud": providerserver.NewProviderServer(testprovider.Provider{ + Resources: map[string]testprovider.Resource{ + "examplecloud_container": examplecloudResource(), + }, + }), + }, + Steps: []r.TestStep{ + { + ConfigDirectory: config.StaticDirectory(`testdata/1`), + }, + { + ResourceName: "examplecloud_container.test", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + func TestImportCommand_ImportStateVerify_Ignore(t *testing.T) { t.Parallel() diff --git a/helper/resource/testing_new.go b/helper/resource/testing_new.go index ea66b67b..5ae7a5b4 100644 --- a/helper/resource/testing_new.go +++ b/helper/resource/testing_new.go @@ -131,7 +131,7 @@ func runNewTest(ctx context.Context, t testing.T, c TestCase, helper *plugintest // use this to track last step successfully applied // acts as default for import tests - var appliedCfg string + var appliedCfg teststep.Config var stepNumber int for stepIndex, step := range c.Steps { @@ -418,7 +418,7 @@ func runNewTest(ctx context.Context, t testing.T, c TestCase, helper *plugintest } } - appliedCfg, err = step.mergedConfig(ctx, c, hasTerraformBlock, hasProviderBlock, helper.TerraformVersion()) + mergedConfig, err := step.mergedConfig(ctx, c, hasTerraformBlock, hasProviderBlock, helper.TerraformVersion()) if err != nil { logging.HelperResourceError(ctx, @@ -428,6 +428,19 @@ func runNewTest(ctx context.Context, t testing.T, c TestCase, helper *plugintest t.Fatalf("Error generating merged configuration: %s", err) } + // Preserve the step config for future test steps to use (import state) + confRequest := teststep.PrepareConfigurationRequest{ + Directory: step.ConfigDirectory, + File: step.ConfigFile, + Raw: mergedConfig, + TestStepConfigRequest: config.TestStepConfigRequest{ + StepNumber: stepNumber, + TestName: t.Name(), + }, + }.Exec() + + appliedCfg = teststep.Configuration(confRequest) + logging.HelperResourceDebug(ctx, "Finished TestStep") continue diff --git a/helper/resource/testing_new_import_state.go b/helper/resource/testing_new_import_state.go index 82a10483..d2d71311 100644 --- a/helper/resource/testing_new_import_state.go +++ b/helper/resource/testing_new_import_state.go @@ -25,7 +25,7 @@ import ( "github.com/hashicorp/terraform-plugin-testing/tfversion" ) -func testStepNewImportState(ctx context.Context, t testing.T, helper *plugintest.Helper, testCaseWorkingDir *plugintest.WorkingDir, step TestStep, cfgRaw string, providers *providerFactories, stepNumber int) error { +func testStepNewImportState(ctx context.Context, t testing.T, helper *plugintest.Helper, testCaseWorkingDir *plugintest.WorkingDir, step TestStep, priorStepCfg teststep.Config, providers *providerFactories, stepNumber int) error { t.Helper() // step.ImportStateKind implicitly defaults to the zero-value (ImportCommandWithID) for backward compatibility @@ -105,12 +105,6 @@ func testStepNewImportState(ctx context.Context, t testing.T, helper *plugintest } } - var inlineConfig string - if step.Config != "" { - inlineConfig = step.Config - } else { - inlineConfig = cfgRaw - } testStepConfigRequest := config.TestStepConfigRequest{ StepNumber: stepNumber, TestName: t.Name(), @@ -118,10 +112,21 @@ func testStepNewImportState(ctx context.Context, t testing.T, helper *plugintest testStepConfig := teststep.Configuration(teststep.PrepareConfigurationRequest{ Directory: step.ConfigDirectory, File: step.ConfigFile, - Raw: inlineConfig, + Raw: step.Config, TestStepConfigRequest: testStepConfigRequest, }.Exec()) + // If the current import state test step doesn't have configuration, use the prior test step config + if testStepConfig == nil { + if priorStepCfg == nil { + t.Fatal("Cannot import state with no specified config") + } + + logging.HelperResourceTrace(ctx, "Using prior TestStep Config for import") + + testStepConfig = priorStepCfg + } + switch { case step.ImportStateConfigExact: break @@ -133,10 +138,6 @@ func testStepNewImportState(ctx context.Context, t testing.T, helper *plugintest testStepConfig = appendImportBlock(testStepConfig, resourceName, importId) } - if testStepConfig == nil { - t.Fatal("Cannot import state with no specified config") - } - var workingDir *plugintest.WorkingDir if importStatePersist { workingDir = testCaseWorkingDir