From 4a0ef42677decf18bf819644290b661a22d2fdd2 Mon Sep 17 00:00:00 2001 From: Baraa Basata Date: Mon, 28 Apr 2025 09:17:34 -0400 Subject: [PATCH 01/27] Add testdata for a writeable config directory --- .../examplecloud_container_import_with_identity.tf | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 helper/resource/importstate/testdata/writeable-config-directory/examplecloud_container_import_with_identity.tf diff --git a/helper/resource/importstate/testdata/writeable-config-directory/examplecloud_container_import_with_identity.tf b/helper/resource/importstate/testdata/writeable-config-directory/examplecloud_container_import_with_identity.tf new file mode 100644 index 00000000..9412afb9 --- /dev/null +++ b/helper/resource/importstate/testdata/writeable-config-directory/examplecloud_container_import_with_identity.tf @@ -0,0 +1,14 @@ +# Copyright (c) HashiCorp, Inc. +# SPDX-License-Identifier: MPL-2.0 + +resource "examplecloud_container" "test" { + name = "somevalue" + location = "westeurope" +} + +import { + to = examplecloud_container.test + identity = { + id = "examplecloud_container.test" + } +} From 6e8a7ed573ec7ae61b0a4cd24f3ef8099bf349ad Mon Sep 17 00:00:00 2001 From: Baraa Basata Date: Mon, 28 Apr 2025 09:18:12 -0400 Subject: [PATCH 02/27] Add testdata for a writeable config file --- .../examplecloud_container_import_with_identity.tf | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 helper/resource/importstate/testdata/writeable-config-file/examplecloud_container_import_with_identity.tf diff --git a/helper/resource/importstate/testdata/writeable-config-file/examplecloud_container_import_with_identity.tf b/helper/resource/importstate/testdata/writeable-config-file/examplecloud_container_import_with_identity.tf new file mode 100644 index 00000000..9412afb9 --- /dev/null +++ b/helper/resource/importstate/testdata/writeable-config-file/examplecloud_container_import_with_identity.tf @@ -0,0 +1,14 @@ +# Copyright (c) HashiCorp, Inc. +# SPDX-License-Identifier: MPL-2.0 + +resource "examplecloud_container" "test" { + name = "somevalue" + location = "westeurope" +} + +import { + to = examplecloud_container.test + identity = { + id = "examplecloud_container.test" + } +} From 85c46dab1a12952bba4e2115771e0fdc1944a9f7 Mon Sep 17 00:00:00 2001 From: Baraa Basata Date: Mon, 28 Apr 2025 09:24:35 -0400 Subject: [PATCH 03/27] Add TestStep flag to opt out of config modification --- .../import_block_in_config_directory_test.go | 38 +++++++++++++++++-- helper/resource/testing.go | 4 ++ 2 files changed, 38 insertions(+), 4 deletions(-) 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 df6feecb..225be3db 100644 --- a/helper/resource/importstate/import_block_in_config_directory_test.go +++ b/helper/resource/importstate/import_block_in_config_directory_test.go @@ -35,10 +35,40 @@ func TestImportBlock_InConfigDirectory(t *testing.T) { ConfigDirectory: config.StaticDirectory(`testdata/1`), }, { - ResourceName: "examplecloud_container.test", - ImportState: true, - ImportStateKind: r.ImportBlockWithID, - ConfigDirectory: config.StaticDirectory(`testdata/2`), + ResourceName: "examplecloud_container.test", + ImportState: true, + ImportStateKind: r.ImportBlockWithID, + ImportStateReadOnlyConfig: true, // TODO: naming + ConfigDirectory: config.StaticDirectory(`testdata/2`), + }, + }, + }) +} + +func TestImportBlock_InConfigDirectory_Writeable(t *testing.T) { + t.Parallel() + + r.UnitTest(t, r.TestCase{ + TerraformVersionChecks: []tfversion.TerraformVersionCheck{ + tfversion.SkipBelow(tfversion.Version1_5_0), // ImportBlockWithID requires Terraform 1.5.0 or later + }, + 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, + ImportStateKind: r.ImportBlockWithID, + ImportStateReadOnlyConfig: false, + ConfigDirectory: config.StaticDirectory(`testdata/helper/writeable-config-directory`), }, }, }) diff --git a/helper/resource/testing.go b/helper/resource/testing.go index 0cfba499..5ee6f74d 100644 --- a/helper/resource/testing.go +++ b/helper/resource/testing.go @@ -666,6 +666,10 @@ type TestStep struct { ImportStateKind ImportStateKind + // ImportStateReadOnlyConfig indicates that the test framework should not + // modify ConfigFile or ConfigDirectory inputs to the test step. + ImportStateReadOnlyConfig bool + // ImportStateId is the ID to perform an ImportState operation with. // This is optional. If it isn't set, then the resource ID is automatically // determined by inspecting the state for ResourceName's ID. From 21e8d544eae00dd49b6d391da1f46c2e8391b865 Mon Sep 17 00:00:00 2001 From: Baraa Basata Date: Mon, 28 Apr 2025 09:27:16 -0400 Subject: [PATCH 04/27] A failing test --- .../importstate/import_block_in_config_directory_test.go | 2 +- .../examplecloud_container_import_with_identity.tf | 7 ------- 2 files changed, 1 insertion(+), 8 deletions(-) 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 225be3db..da5e962b 100644 --- a/helper/resource/importstate/import_block_in_config_directory_test.go +++ b/helper/resource/importstate/import_block_in_config_directory_test.go @@ -68,7 +68,7 @@ func TestImportBlock_InConfigDirectory_Writeable(t *testing.T) { ImportState: true, ImportStateKind: r.ImportBlockWithID, ImportStateReadOnlyConfig: false, - ConfigDirectory: config.StaticDirectory(`testdata/helper/writeable-config-directory`), + ConfigDirectory: config.StaticDirectory(`testdata/writeable-config-directory`), }, }, }) diff --git a/helper/resource/importstate/testdata/writeable-config-directory/examplecloud_container_import_with_identity.tf b/helper/resource/importstate/testdata/writeable-config-directory/examplecloud_container_import_with_identity.tf index 9412afb9..ccfb698e 100644 --- a/helper/resource/importstate/testdata/writeable-config-directory/examplecloud_container_import_with_identity.tf +++ b/helper/resource/importstate/testdata/writeable-config-directory/examplecloud_container_import_with_identity.tf @@ -5,10 +5,3 @@ resource "examplecloud_container" "test" { name = "somevalue" location = "westeurope" } - -import { - to = examplecloud_container.test - identity = { - id = "examplecloud_container.test" - } -} From c1aafe4eb3aae53070d426f5667d6b1a915aab16 Mon Sep 17 00:00:00 2001 From: Baraa Basata Date: Mon, 28 Apr 2025 12:35:21 -0400 Subject: [PATCH 05/27] Prepare to add a field to configDirectory --- internal/teststep/directory_test.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/internal/teststep/directory_test.go b/internal/teststep/directory_test.go index 0118b91d..16f55d9a 100644 --- a/internal/teststep/directory_test.go +++ b/internal/teststep/directory_test.go @@ -432,17 +432,17 @@ func TestConfigurationDirectory_Write(t *testing.T) { }, "no-config": { configDirectory: configurationDirectory{ - "testdata/empty_dir", + directory: "testdata/empty_dir", }, }, "dir-single-file": { configDirectory: configurationDirectory{ - "testdata/random", + directory: "testdata/random", }, }, "dir-multiple-files": { configDirectory: configurationDirectory{ - "testdata/random_multiple_files", + directory: "testdata/random_multiple_files", }, }, } @@ -523,17 +523,17 @@ func TestConfigurationDirectory_Write_AbsolutePath(t *testing.T) { }, "no-config": { configDirectory: configurationDirectory{ - "testdata/empty_dir", + directory: "testdata/empty_dir", }, }, "dir-single-file": { configDirectory: configurationDirectory{ - "testdata/random", + directory: "testdata/random", }, }, "dir-multiple-files": { configDirectory: configurationDirectory{ - "testdata/random_multiple_files", + directory: "testdata/random_multiple_files", }, }, } From 748d9d5391c0c7f4ed3311474452ddb7bcf6fdae Mon Sep 17 00:00:00 2001 From: Baraa Basata Date: Mon, 28 Apr 2025 12:56:16 -0400 Subject: [PATCH 06/27] Accept optional generated config for a config directory --- internal/teststep/config.go | 1 + internal/teststep/directory.go | 39 ++++++++++++++- internal/teststep/directory_test.go | 75 +++++++++++++++++++++++++++++ internal/teststep/file.go | 4 ++ internal/teststep/string.go | 6 +++ 5 files changed, 124 insertions(+), 1 deletion(-) diff --git a/internal/teststep/config.go b/internal/teststep/config.go index b81c264d..7e07bb34 100644 --- a/internal/teststep/config.go +++ b/internal/teststep/config.go @@ -45,6 +45,7 @@ type Config interface { HasProviderBlock(context.Context) (bool, error) HasTerraformBlock(context.Context) (bool, error) Write(context.Context, string) error + AppendGeneratedConfig(context.Context, string) Config } // PrepareConfigurationRequest is used to simplify the generation of diff --git a/internal/teststep/directory.go b/internal/teststep/directory.go index 0126e82a..91ee86b7 100644 --- a/internal/teststep/directory.go +++ b/internal/teststep/directory.go @@ -5,14 +5,18 @@ package teststep import ( "context" + "fmt" + "hash/crc32" "os" "path/filepath" ) var _ Config = configurationDirectory{} +// not threadsafe type configurationDirectory struct { - directory string + directory string + generatedFiles map[string]string } // HasConfigurationFiles is used during validation to ensure that @@ -85,10 +89,43 @@ func (c configurationDirectory) Write(ctx context.Context, dest string) error { } err := copyFiles(configDirectory, dest) + if err != nil { + return err + } + err = c.writeGeneratedFiles(dest) if err != nil { return err } return nil } + +func (c configurationDirectory) AppendGeneratedConfig(_ context.Context, config string) Config { + if c.generatedFiles == nil { + c.generatedFiles = make(map[string]string) + } + + checksum := crc32.Checksum([]byte(config), crc32.IEEETable) + filename := fmt.Sprintf("terraform_plugin_test_%d.tf", checksum) + + fmt.Println("Appending generated file:", filename) + c.generatedFiles[filename] = config + return c +} + +func (c configurationDirectory) writeGeneratedFiles(dstPath string) error { + fmt.Println("Count of generated files:", len(c.generatedFiles)) + for filename, config := range c.generatedFiles { + outFilename := filepath.Join(dstPath, filename) + fmt.Println("Writing generated file:", outFilename) + + err := os.WriteFile(outFilename, []byte(config), 0700) + if err != nil { + return err + } + fmt.Println("Wrote generated file:", outFilename) + } + + return nil +} diff --git a/internal/teststep/directory_test.go b/internal/teststep/directory_test.go index 16f55d9a..f64419f2 100644 --- a/internal/teststep/directory_test.go +++ b/internal/teststep/directory_test.go @@ -607,6 +607,81 @@ func TestConfigurationDirectory_Write_AbsolutePath(t *testing.T) { } } +func TestConfigurationDirectory_Write_WithGeneratedFiles(t *testing.T) { + t.Parallel() + + testCases := map[string]struct { + configDirectory configurationDirectory + expectedError *regexp.Regexp + }{ + "dir-single-file": { + configDirectory: configurationDirectory{ + directory: "testdata/random", + generatedFiles: map[string]string{ + "import.tf": `terraform {\nimport\n{\nto = satellite.the_moon\nid = "moon"\n}\n}\n`, + }, + }, + }, + } + + for name, testCase := range testCases { + t.Run(name, func(t *testing.T) { + t.Parallel() + + tempDir := t.TempDir() + + err := testCase.configDirectory.Write(context.Background(), tempDir) + if err != nil { + t.Errorf("unexpected error %s", err) + } + + dirEntries, err := os.ReadDir(testCase.configDirectory.directory) + if err != nil { + t.Errorf("error reading directory: %s", err) + } + + tempDirEntries, err := os.ReadDir(tempDir) + + if err != nil { + t.Errorf("error reading temp directory: %s", err) + } + + if len(tempDirEntries)-len(dirEntries) != 1 { + t.Errorf("expected %d dir entries, got %d dir entries", len(dirEntries)+1, tempDirEntries) + } + + for _, entry := range dirEntries { + filename := entry.Name() + expectedContent, err := os.ReadFile(filepath.Join(testCase.configDirectory.directory, filename)) + if err != nil { + t.Errorf("error reading file from config directory %s: %s", filename, err) + } + + content, err := os.ReadFile(filepath.Join(tempDir, filename)) + if err != nil { + t.Errorf("error reading generated file %s: %s", filename, err) + } + + if diff := cmp.Diff(expectedContent, content); diff != "" { + t.Errorf("unexpected difference: %s", diff) + } + } + + generatedFiles := testCase.configDirectory.generatedFiles + for filename, expectedContent := range generatedFiles { + content, err := os.ReadFile(filepath.Join(tempDir, filename)) + if err != nil { + t.Errorf("error reading generated file %s: %s", filename, err) + } + + if diff := cmp.Diff([]byte(expectedContent), content); diff != "" { + t.Errorf("unexpected difference: %s", diff) + } + } + }) + } +} + var fileInfoComparer = cmp.Comparer(func(x, y os.FileInfo) bool { if x.Name() != y.Name() { return false diff --git a/internal/teststep/file.go b/internal/teststep/file.go index 6de3f075..a27c2807 100644 --- a/internal/teststep/file.go +++ b/internal/teststep/file.go @@ -92,3 +92,7 @@ func (c configurationFile) Write(ctx context.Context, dest string) error { return nil } + +func (c configurationFile) AppendGeneratedConfig(_ context.Context, config string) Config { + return c +} diff --git a/internal/teststep/string.go b/internal/teststep/string.go index 4143b484..6c0b1dc3 100644 --- a/internal/teststep/string.go +++ b/internal/teststep/string.go @@ -57,5 +57,11 @@ func (c configurationString) Write(ctx context.Context, dest string) error { return err } + fmt.Println("Wrote config to", outFilename) + return nil } + +func (c configurationString) AppendGeneratedConfig(_ context.Context, config string) Config { + return c +} From c53eb2450f80334f08912d1b67ad279383914674 Mon Sep 17 00:00:00 2001 From: Baraa Basata Date: Mon, 28 Apr 2025 12:57:56 -0400 Subject: [PATCH 07/27] Write generated import config to ConfigDirectory With `step.ImportStateReadOnlyConfig` opt-out flag --- helper/resource/testing_new_import_state.go | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/helper/resource/testing_new_import_state.go b/helper/resource/testing_new_import_state.go index 88770718..016d7272 100644 --- a/helper/resource/testing_new_import_state.go +++ b/helper/resource/testing_new_import_state.go @@ -116,7 +116,8 @@ func testStepNewImportState(ctx context.Context, t testing.T, helper *plugintest TestStepConfigRequest: testStepConfigRequest, }.Exec()) - if testStepConfig == nil { + switch { + case testStepConfig == nil: logging.HelperResourceTrace(ctx, "Using prior TestStep Config for import") importConfig := cfgRaw @@ -133,6 +134,24 @@ func testStepNewImportState(ctx context.Context, t testing.T, helper *plugintest if testStepConfig == nil { t.Fatal("Cannot import state with no specified config") } + + case step.ImportStateReadOnlyConfig: + break + + case step.ConfigDirectory != nil: + // TODO: extract / DRY + + importConfig := "" + if kind.plannable() && kind.resourceIdentity() { + importConfig = appendImportBlockWithIdentity(importConfig, resourceName, priorIdentityValues) + } else if kind.plannable() { + importConfig = appendImportBlock(importConfig, resourceName, importId) + } + testStepConfig = testStepConfig.AppendGeneratedConfig(ctx, importConfig) + + case step.ConfigFile != nil: + // TODO: ship it + } var workingDir *plugintest.WorkingDir From f4c6492bb0bb2ac29ba0d6a5433ec2bf3ec152b9 Mon Sep 17 00:00:00 2001 From: Baraa Basata Date: Wed, 30 Apr 2025 16:29:05 -0400 Subject: [PATCH 08/27] Rename to Append() --- helper/resource/testing_new_import_state.go | 2 +- internal/teststep/config.go | 18 +++++++++++++++++- internal/teststep/directory.go | 2 +- internal/teststep/file.go | 18 ++++++++++++++---- internal/teststep/string.go | 7 +++++-- 5 files changed, 38 insertions(+), 9 deletions(-) diff --git a/helper/resource/testing_new_import_state.go b/helper/resource/testing_new_import_state.go index 016d7272..8e26f12f 100644 --- a/helper/resource/testing_new_import_state.go +++ b/helper/resource/testing_new_import_state.go @@ -147,7 +147,7 @@ func testStepNewImportState(ctx context.Context, t testing.T, helper *plugintest } else if kind.plannable() { importConfig = appendImportBlock(importConfig, resourceName, importId) } - testStepConfig = testStepConfig.AppendGeneratedConfig(ctx, importConfig) + testStepConfig = testStepConfig.Append(ctx, importConfig) case step.ConfigFile != nil: // TODO: ship it diff --git a/internal/teststep/config.go b/internal/teststep/config.go index 7e07bb34..8220d638 100644 --- a/internal/teststep/config.go +++ b/internal/teststep/config.go @@ -45,7 +45,7 @@ type Config interface { HasProviderBlock(context.Context) (bool, error) HasTerraformBlock(context.Context) (bool, error) Write(context.Context, string) error - AppendGeneratedConfig(context.Context, string) Config + Append(context.Context, string) Config } // PrepareConfigurationRequest is used to simplify the generation of @@ -200,6 +200,22 @@ func copyFile(path string, dstPath string) error { return nil } +// appendToFile accepts a path to a file and a string, +// appending the file from path to destination. +func appendToFile(path string, content string) error { + f, err := os.OpenFile(path, os.O_APPEND, os.ModeAppend) + if err != nil { + return err + } + defer f.Close() + + if _, err := io.WriteString(f, content); err != nil { + return err + } + + return nil +} + // filesContains accepts a string representing a directory and a // regular expression. For each file that is found within the // directory fileContains func is called. Any nested directories diff --git a/internal/teststep/directory.go b/internal/teststep/directory.go index 91ee86b7..fd793cc1 100644 --- a/internal/teststep/directory.go +++ b/internal/teststep/directory.go @@ -101,7 +101,7 @@ func (c configurationDirectory) Write(ctx context.Context, dest string) error { return nil } -func (c configurationDirectory) AppendGeneratedConfig(_ context.Context, config string) Config { +func (c configurationDirectory) Append(_ context.Context, config string) Config { if c.generatedFiles == nil { c.generatedFiles = make(map[string]string) } diff --git a/internal/teststep/file.go b/internal/teststep/file.go index a27c2807..aba85ce5 100644 --- a/internal/teststep/file.go +++ b/internal/teststep/file.go @@ -12,7 +12,8 @@ import ( var _ Config = configurationFile{} type configurationFile struct { - file string + file string + appendedConfig string } // HasConfigurationFiles is used during validation to ensure that @@ -85,14 +86,23 @@ func (c configurationFile) Write(ctx context.Context, dest string) error { } err := copyFile(configFile, dest) - if err != nil { return err } + if len(c.appendedConfig) > 0 { + err := appendToFile(configFile, c.appendedConfig) + if err != nil { + return err + } + } + return nil } -func (c configurationFile) AppendGeneratedConfig(_ context.Context, config string) Config { - return c +func (c configurationFile) Append(_ context.Context, config string) Config { + return configurationFile{ + file: c.file, + appendedConfig: config, + } } diff --git a/internal/teststep/string.go b/internal/teststep/string.go index 6c0b1dc3..6ae654ef 100644 --- a/internal/teststep/string.go +++ b/internal/teststep/string.go @@ -9,6 +9,7 @@ import ( "fmt" "os" "path/filepath" + "strings" ) var _ Config = configurationString{} @@ -62,6 +63,8 @@ func (c configurationString) Write(ctx context.Context, dest string) error { return nil } -func (c configurationString) AppendGeneratedConfig(_ context.Context, config string) Config { - return c +func (c configurationString) Append(_ context.Context, config string) Config { + return configurationString{ + raw: strings.Join([]string{c.raw, config}, "\n"), + } } From cdc70c161ced9242442bf1907539d6f37d0f0547 Mon Sep 17 00:00:00 2001 From: Baraa Basata Date: Wed, 30 Apr 2025 16:33:34 -0400 Subject: [PATCH 09/27] Refactor to Append() --- helper/resource/testing_new_import_state.go | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/helper/resource/testing_new_import_state.go b/helper/resource/testing_new_import_state.go index 8e26f12f..a0c52332 100644 --- a/helper/resource/testing_new_import_state.go +++ b/helper/resource/testing_new_import_state.go @@ -119,18 +119,21 @@ func testStepNewImportState(ctx context.Context, t testing.T, helper *plugintest switch { case testStepConfig == nil: logging.HelperResourceTrace(ctx, "Using prior TestStep Config for import") - importConfig := cfgRaw + testStepConfig = teststep.Configuration(teststep.PrepareConfigurationRequest{ + Raw: cfgRaw, + TestStepConfigRequest: testStepConfigRequest, + }.Exec()) + + importConfig := "" if kind.plannable() && kind.resourceIdentity() { importConfig = appendImportBlockWithIdentity(importConfig, resourceName, priorIdentityValues) } else if kind.plannable() { importConfig = appendImportBlock(importConfig, resourceName, importId) } - testStepConfig = teststep.Configuration(teststep.PrepareConfigurationRequest{ - Raw: importConfig, - TestStepConfigRequest: testStepConfigRequest, - }.Exec()) + testStepConfig = testStepConfig.Append(ctx, importConfig) + if testStepConfig == nil { t.Fatal("Cannot import state with no specified config") } From 2ef656a6e27a282ef4d06a5e46e3cc5dc2dc89b2 Mon Sep 17 00:00:00 2001 From: Baraa Basata Date: Wed, 30 Apr 2025 16:41:27 -0400 Subject: [PATCH 10/27] Refactor to append() style --- helper/resource/testing_new_import_state.go | 52 ++++++++++----------- 1 file changed, 24 insertions(+), 28 deletions(-) diff --git a/helper/resource/testing_new_import_state.go b/helper/resource/testing_new_import_state.go index a0c52332..eba2cbe0 100644 --- a/helper/resource/testing_new_import_state.go +++ b/helper/resource/testing_new_import_state.go @@ -125,15 +125,12 @@ func testStepNewImportState(ctx context.Context, t testing.T, helper *plugintest TestStepConfigRequest: testStepConfigRequest, }.Exec()) - importConfig := "" if kind.plannable() && kind.resourceIdentity() { - importConfig = appendImportBlockWithIdentity(importConfig, resourceName, priorIdentityValues) + testStepConfig = appendImportBlockWithIdentity(testStepConfig, resourceName, priorIdentityValues) } else if kind.plannable() { - importConfig = appendImportBlock(importConfig, resourceName, importId) + testStepConfig = appendImportBlock(testStepConfig, resourceName, importId) } - testStepConfig = testStepConfig.Append(ctx, importConfig) - if testStepConfig == nil { t.Fatal("Cannot import state with no specified config") } @@ -144,13 +141,11 @@ func testStepNewImportState(ctx context.Context, t testing.T, helper *plugintest case step.ConfigDirectory != nil: // TODO: extract / DRY - importConfig := "" if kind.plannable() && kind.resourceIdentity() { - importConfig = appendImportBlockWithIdentity(importConfig, resourceName, priorIdentityValues) + testStepConfig = appendImportBlockWithIdentity(testStepConfig, resourceName, priorIdentityValues) } else if kind.plannable() { - importConfig = appendImportBlock(importConfig, resourceName, importId) + testStepConfig = appendImportBlock(testStepConfig, resourceName, importId) } - testStepConfig = testStepConfig.Append(ctx, importConfig) case step.ConfigFile != nil: // TODO: ship it @@ -446,51 +441,52 @@ func testImportCommand(ctx context.Context, t testing.T, workingDir *plugintest. return nil } -func appendImportBlock(config string, resourceName string, importID string) string { - return config + fmt.Sprintf(``+"\n"+ - `import {`+"\n"+ - ` to = %s`+"\n"+ - ` id = %q`+"\n"+ - `}`, - resourceName, importID) +func appendImportBlock(config teststep.Config, resourceName string, importID string) teststep.Config { + return config.Append( + context.Background(), // TODO: remove + fmt.Sprintf(``+"\n"+ + `import {`+"\n"+ + ` to = %s`+"\n"+ + ` id = %q`+"\n"+ + `}`, + resourceName, importID)) } -func appendImportBlockWithIdentity(config string, resourceName string, identityValues map[string]any) string { - configBuilder := config - configBuilder += fmt.Sprintf(``+"\n"+ +func appendImportBlockWithIdentity(config teststep.Config, resourceName string, identityValues map[string]any) teststep.Config { + configBuilder := strings.Builder{} + configBuilder.WriteString(fmt.Sprintf(``+"\n"+ `import {`+"\n"+ ` to = %s`+"\n"+ ` identity = {`+"\n", - resourceName) + resourceName)) for k, v := range identityValues { switch v := v.(type) { case bool: - configBuilder += fmt.Sprintf(` %q = %t`+"\n", k, v) + configBuilder.WriteString(fmt.Sprintf(` %q = %t`+"\n", k, v)) case []any: var quotedV []string for _, v := range v { quotedV = append(quotedV, fmt.Sprintf(`%q`, v)) } - configBuilder += fmt.Sprintf(` %q = [%s]`+"\n", k, strings.Join(quotedV, ", ")) + configBuilder.WriteString(fmt.Sprintf(` %q = [%s]`+"\n", k, strings.Join(quotedV, ", "))) case json.Number: - configBuilder += fmt.Sprintf(` %q = %s`+"\n", k, v) + configBuilder.WriteString(fmt.Sprintf(` %q = %s`+"\n", k, v)) case string: - configBuilder += fmt.Sprintf(` %q = %q`+"\n", k, v) + configBuilder.WriteString(fmt.Sprintf(` %q = %q`+"\n", k, v)) default: panic(fmt.Sprintf("unexpected type %T for identity value %q", v, k)) } } - configBuilder += `` + - ` }` + "\n" + - `}` + "\n" + configBuilder.WriteString(` }` + "\n") + configBuilder.WriteString(`}` + "\n") - return configBuilder + return config.Append(context.Background(), configBuilder.String()) } func importStatePreconditions(t testing.T, helper *plugintest.Helper, step TestStep) error { From 07b1779882b2cf93a3f73d6603a9ddb2250ead47 Mon Sep 17 00:00:00 2001 From: Baraa Basata Date: Fri, 2 May 2025 12:09:59 -0400 Subject: [PATCH 11/27] Rename to step.ConfigExact --- .../import_block_in_config_directory_test.go | 20 +++++++++---------- helper/resource/testing.go | 14 +++++++++---- helper/resource/testing_new_import_state.go | 2 +- 3 files changed, 21 insertions(+), 15 deletions(-) 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 da5e962b..c06d3e89 100644 --- a/helper/resource/importstate/import_block_in_config_directory_test.go +++ b/helper/resource/importstate/import_block_in_config_directory_test.go @@ -35,11 +35,11 @@ func TestImportBlock_InConfigDirectory(t *testing.T) { ConfigDirectory: config.StaticDirectory(`testdata/1`), }, { - ResourceName: "examplecloud_container.test", - ImportState: true, - ImportStateKind: r.ImportBlockWithID, - ImportStateReadOnlyConfig: true, // TODO: naming - ConfigDirectory: config.StaticDirectory(`testdata/2`), + ResourceName: "examplecloud_container.test", + ImportState: true, + ImportStateKind: r.ImportBlockWithID, + ConfigDirectory: config.StaticDirectory(`testdata/2`), + ConfigExact: true, }, }, }) @@ -64,11 +64,11 @@ func TestImportBlock_InConfigDirectory_Writeable(t *testing.T) { ConfigDirectory: config.StaticDirectory(`testdata/1`), }, { - ResourceName: "examplecloud_container.test", - ImportState: true, - ImportStateKind: r.ImportBlockWithID, - ImportStateReadOnlyConfig: false, - ConfigDirectory: config.StaticDirectory(`testdata/writeable-config-directory`), + ResourceName: "examplecloud_container.test", + ImportState: true, + ImportStateKind: r.ImportBlockWithID, + ConfigDirectory: config.StaticDirectory(`testdata/writeable-config-directory`), + ConfigExact: false, }, }, }) diff --git a/helper/resource/testing.go b/helper/resource/testing.go index 5ee6f74d..367794b3 100644 --- a/helper/resource/testing.go +++ b/helper/resource/testing.go @@ -576,6 +576,16 @@ type TestStep struct { // otherwise an error will be returned. ConfigFile config.TestStepConfigFunc + // ConfigExact indicates that the test framework should use the exact + // content of the Config, ConfigFile, or ConfigDirectory inputs and should + // not modify it at test run time. + // + // The default is false. At test run time, the test framework will generate + // specific kinds of configuration, such as import blocks, and append them + // to the given Config, ConfigFile, or ConfigDirectory inputs. Using this + // default improves test readability and removes duplication of setup. + ConfigExact bool + // ConfigVariables is a map defining variables for use in conjunction // with Terraform configuration. If this map is populated then it // will be used to assemble an *.auto.tfvars.json which will be @@ -666,10 +676,6 @@ type TestStep struct { ImportStateKind ImportStateKind - // ImportStateReadOnlyConfig indicates that the test framework should not - // modify ConfigFile or ConfigDirectory inputs to the test step. - ImportStateReadOnlyConfig bool - // ImportStateId is the ID to perform an ImportState operation with. // This is optional. If it isn't set, then the resource ID is automatically // determined by inspecting the state for ResourceName's ID. diff --git a/helper/resource/testing_new_import_state.go b/helper/resource/testing_new_import_state.go index eba2cbe0..077584e1 100644 --- a/helper/resource/testing_new_import_state.go +++ b/helper/resource/testing_new_import_state.go @@ -135,7 +135,7 @@ func testStepNewImportState(ctx context.Context, t testing.T, helper *plugintest t.Fatal("Cannot import state with no specified config") } - case step.ImportStateReadOnlyConfig: + case step.ConfigExact: break case step.ConfigDirectory != nil: From 1dae6f8589e9278ab074077c2c45016843a648c1 Mon Sep 17 00:00:00 2001 From: Baraa Basata Date: Fri, 2 May 2025 12:17:00 -0400 Subject: [PATCH 12/27] lint --- internal/teststep/file_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/teststep/file_test.go b/internal/teststep/file_test.go index 5d0ebb73..118dd002 100644 --- a/internal/teststep/file_test.go +++ b/internal/teststep/file_test.go @@ -432,7 +432,7 @@ func TestConfigurationFile_Write(t *testing.T) { }, "file": { configFile: configurationFile{ - "testdata/random/random.tf", + file: "testdata/random/random.tf", }, }, } @@ -495,7 +495,7 @@ func TestConfigurationFile_Write_AbsolutePath(t *testing.T) { }, "file": { configFile: configurationFile{ - "testdata/random/random.tf", + file: "testdata/random/random.tf", }, }, } From b5f05da4897df0280d131f0128b51b660a302fff Mon Sep 17 00:00:00 2001 From: Baraa Basata Date: Fri, 2 May 2025 16:16:23 -0400 Subject: [PATCH 13/27] Extend ConfigExact to Config and ConfigFile --- .../import_block_as_first_step_test.go | 1 + .../import_block_in_config_directory_test.go | 4 +-- .../import_block_in_config_file_test.go | 31 +++++++++++++++- .../importstate/import_block_with_id_test.go | 3 ++ ..._identity.tf => examplecloud_container.tf} | 7 ---- helper/resource/testing_new_import_state.go | 36 ++++++------------- internal/teststep/config.go | 16 ++++----- internal/teststep/directory.go | 4 --- internal/teststep/file.go | 4 +-- 9 files changed, 57 insertions(+), 49 deletions(-) rename helper/resource/importstate/testdata/writeable-config-file/{examplecloud_container_import_with_identity.tf => examplecloud_container.tf} (60%) diff --git a/helper/resource/importstate/import_block_as_first_step_test.go b/helper/resource/importstate/import_block_as_first_step_test.go index 915c61b3..a3f77fac 100644 --- a/helper/resource/importstate/import_block_as_first_step_test.go +++ b/helper/resource/importstate/import_block_as_first_step_test.go @@ -48,6 +48,7 @@ func TestImportBlock_AsFirstStep(t *testing.T) { id = "westeurope/somevalue" } `, + ConfigExact: true, ImportPlanChecks: r.ImportPlanChecks{ PreApply: []plancheck.PlanCheck{ plancheck.ExpectResourceAction("examplecloud_container.test", plancheck.ResourceActionNoop), 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 c06d3e89..f808af34 100644 --- a/helper/resource/importstate/import_block_in_config_directory_test.go +++ b/helper/resource/importstate/import_block_in_config_directory_test.go @@ -16,7 +16,7 @@ import ( r "github.com/hashicorp/terraform-plugin-testing/helper/resource" ) -func TestImportBlock_InConfigDirectory(t *testing.T) { +func TestImportBlock_InConfigDirectory_ConfigExactTrue(t *testing.T) { t.Parallel() r.UnitTest(t, r.TestCase{ @@ -45,7 +45,7 @@ func TestImportBlock_InConfigDirectory(t *testing.T) { }) } -func TestImportBlock_InConfigDirectory_Writeable(t *testing.T) { +func TestImportBlock_InConfigDirectory(t *testing.T) { t.Parallel() r.UnitTest(t, r.TestCase{ 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 2d5a97a2..757435d0 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,7 @@ func TestImportBlock_InConfigFile(t *testing.T) { ResourceName: "examplecloud_container.test", ImportState: true, ImportStateKind: r.ImportBlockWithID, - ConfigFile: config.StaticFile(`testdata/2/examplecloud_container_import.tf`), + ConfigFile: config.StaticFile(`testdata/writeable-config-file/examplecloud_container.tf`), }, }, }) @@ -58,6 +58,34 @@ func TestImportBlock_WithResourceIdentity_InConfigFile(t *testing.T) { }, }), }, + Steps: []r.TestStep{ + { + ConfigFile: config.StaticFile(`testdata/1/examplecloud_container.tf`), + }, + { + ResourceName: "examplecloud_container.test", + ImportState: true, + ImportStateKind: r.ImportBlockWithResourceIdentity, + ConfigFile: config.StaticFile(`testdata/writeable-config-file/examplecloud_container.tf`), + }, + }, + }) +} + +func TestImportBlock_InConfigFile_ConfigExactTrue(t *testing.T) { + t.Parallel() + + r.UnitTest(t, r.TestCase{ + TerraformVersionChecks: []tfversion.TerraformVersionCheck{ + tfversion.SkipBelow(tfversion.Version1_5_0), // ImportBlockWithID requires Terraform 1.5.0 or later + }, + 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`), @@ -67,6 +95,7 @@ func TestImportBlock_WithResourceIdentity_InConfigFile(t *testing.T) { ImportState: true, ImportStateKind: r.ImportBlockWithResourceIdentity, ConfigFile: config.StaticFile(`testdata/examplecloud_container_import_with_identity.tf`), + ConfigExact: true, }, }, }) diff --git a/helper/resource/importstate/import_block_with_id_test.go b/helper/resource/importstate/import_block_with_id_test.go index ef966150..9a14577b 100644 --- a/helper/resource/importstate/import_block_with_id_test.go +++ b/helper/resource/importstate/import_block_with_id_test.go @@ -89,6 +89,7 @@ func TestImportBlock_WithID_ExpectError(t *testing.T) { id = "westeurope/somevalue" } `, + ConfigExact: true, ResourceName: "examplecloud_container.test", ImportState: true, ImportStateKind: r.ImportBlockWithID, @@ -295,6 +296,7 @@ func TestImportBlock_WithID_WithBlankOptionalAttribute_GeneratesCorrectPlan(t *t id = "sometestid" }`, + ConfigExact: true, ResourceName: "examplecloud_container.test", ImportState: true, ImportStateKind: r.ImportBlockWithID, @@ -419,6 +421,7 @@ import { ImportState: true, ImportStateKind: r.ImportBlockWithID, Config: configWithImportBlock, + ConfigExact: true, ResourceName: "random_string.mystery_message", ImportPlanChecks: r.ImportPlanChecks{ PreApply: []plancheck.PlanCheck{ diff --git a/helper/resource/importstate/testdata/writeable-config-file/examplecloud_container_import_with_identity.tf b/helper/resource/importstate/testdata/writeable-config-file/examplecloud_container.tf similarity index 60% rename from helper/resource/importstate/testdata/writeable-config-file/examplecloud_container_import_with_identity.tf rename to helper/resource/importstate/testdata/writeable-config-file/examplecloud_container.tf index 9412afb9..ccfb698e 100644 --- a/helper/resource/importstate/testdata/writeable-config-file/examplecloud_container_import_with_identity.tf +++ b/helper/resource/importstate/testdata/writeable-config-file/examplecloud_container.tf @@ -5,10 +5,3 @@ resource "examplecloud_container" "test" { name = "somevalue" location = "westeurope" } - -import { - to = examplecloud_container.test - identity = { - id = "examplecloud_container.test" - } -} diff --git a/helper/resource/testing_new_import_state.go b/helper/resource/testing_new_import_state.go index 077584e1..86ef02ed 100644 --- a/helper/resource/testing_new_import_state.go +++ b/helper/resource/testing_new_import_state.go @@ -105,6 +105,12 @@ 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(), @@ -112,44 +118,24 @@ func testStepNewImportState(ctx context.Context, t testing.T, helper *plugintest testStepConfig := teststep.Configuration(teststep.PrepareConfigurationRequest{ Directory: step.ConfigDirectory, File: step.ConfigFile, - Raw: step.Config, + Raw: inlineConfig, TestStepConfigRequest: testStepConfigRequest, }.Exec()) switch { - case testStepConfig == nil: - logging.HelperResourceTrace(ctx, "Using prior TestStep Config for import") - - testStepConfig = teststep.Configuration(teststep.PrepareConfigurationRequest{ - Raw: cfgRaw, - TestStepConfigRequest: testStepConfigRequest, - }.Exec()) - - if kind.plannable() && kind.resourceIdentity() { - testStepConfig = appendImportBlockWithIdentity(testStepConfig, resourceName, priorIdentityValues) - } else if kind.plannable() { - testStepConfig = appendImportBlock(testStepConfig, resourceName, importId) - } - - if testStepConfig == nil { - t.Fatal("Cannot import state with no specified config") - } - case step.ConfigExact: break - case step.ConfigDirectory != nil: - // TODO: extract / DRY - + default: if kind.plannable() && kind.resourceIdentity() { testStepConfig = appendImportBlockWithIdentity(testStepConfig, resourceName, priorIdentityValues) } else if kind.plannable() { testStepConfig = appendImportBlock(testStepConfig, resourceName, importId) } + } - case step.ConfigFile != nil: - // TODO: ship it - + if testStepConfig == nil { + t.Fatal("Cannot import state with no specified config") } var workingDir *plugintest.WorkingDir diff --git a/internal/teststep/config.go b/internal/teststep/config.go index 8220d638..be4ad0ce 100644 --- a/internal/teststep/config.go +++ b/internal/teststep/config.go @@ -152,7 +152,7 @@ func copyFiles(path string, dstPath string) error { if info.IsDir() { continue } else { - err = copyFile(srcPath, dstPath) + _, err = copyFile(srcPath, dstPath) if err != nil { return err @@ -165,11 +165,11 @@ func copyFiles(path string, dstPath string) error { // copyFile accepts a path to a file and a destination, // copying the file from path to destination. -func copyFile(path string, dstPath string) error { +func copyFile(path string, dstPath string) (string, error) { srcF, err := os.Open(path) if err != nil { - return err + return "", err } defer srcF.Close() @@ -177,7 +177,7 @@ func copyFile(path string, dstPath string) error { di, err := os.Stat(dstPath) if err != nil { - return err + return "", err } if di.IsDir() { @@ -188,22 +188,22 @@ func copyFile(path string, dstPath string) error { dstF, err := os.Create(dstPath) if err != nil { - return err + return "", err } defer dstF.Close() if _, err := io.Copy(dstF, srcF); err != nil { - return err + return "", err } - return nil + return dstPath, nil } // appendToFile accepts a path to a file and a string, // appending the file from path to destination. func appendToFile(path string, content string) error { - f, err := os.OpenFile(path, os.O_APPEND, os.ModeAppend) + f, err := os.OpenFile(path, os.O_APPEND|os.O_WRONLY, os.ModeAppend) if err != nil { return err } diff --git a/internal/teststep/directory.go b/internal/teststep/directory.go index fd793cc1..30bddd9e 100644 --- a/internal/teststep/directory.go +++ b/internal/teststep/directory.go @@ -109,22 +109,18 @@ func (c configurationDirectory) Append(_ context.Context, config string) Config checksum := crc32.Checksum([]byte(config), crc32.IEEETable) filename := fmt.Sprintf("terraform_plugin_test_%d.tf", checksum) - fmt.Println("Appending generated file:", filename) c.generatedFiles[filename] = config return c } func (c configurationDirectory) writeGeneratedFiles(dstPath string) error { - fmt.Println("Count of generated files:", len(c.generatedFiles)) for filename, config := range c.generatedFiles { outFilename := filepath.Join(dstPath, filename) - fmt.Println("Writing generated file:", outFilename) err := os.WriteFile(outFilename, []byte(config), 0700) if err != nil { return err } - fmt.Println("Wrote generated file:", outFilename) } return nil diff --git a/internal/teststep/file.go b/internal/teststep/file.go index aba85ce5..669b761f 100644 --- a/internal/teststep/file.go +++ b/internal/teststep/file.go @@ -85,13 +85,13 @@ func (c configurationFile) Write(ctx context.Context, dest string) error { configFile = filepath.Join(pwd, configFile) } - err := copyFile(configFile, dest) + destPath, err := copyFile(configFile, dest) if err != nil { return err } if len(c.appendedConfig) > 0 { - err := appendToFile(configFile, c.appendedConfig) + err := appendToFile(destPath, c.appendedConfig) if err != nil { return err } From 52cc5ee37612290b7a9f4683eb99566a0ada0868 Mon Sep 17 00:00:00 2001 From: Baraa Basata Date: Fri, 2 May 2025 16:19:50 -0400 Subject: [PATCH 14/27] fixup! Extend ConfigExact to Config and ConfigFile --- internal/teststep/string.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/internal/teststep/string.go b/internal/teststep/string.go index 6ae654ef..0d004250 100644 --- a/internal/teststep/string.go +++ b/internal/teststep/string.go @@ -58,8 +58,6 @@ func (c configurationString) Write(ctx context.Context, dest string) error { return err } - fmt.Println("Wrote config to", outFilename) - return nil } From d065ac4c15f20db847b263c86748843b4c0faeed Mon Sep 17 00:00:00 2001 From: Baraa Basata Date: Fri, 2 May 2025 16:34:18 -0400 Subject: [PATCH 15/27] Tidy importstate/testdata --- .../import_block_in_config_directory_test.go | 13 ++++++++----- .../importstate/import_block_in_config_file_test.go | 4 ++-- .../examplecloud_container.tf | 0 .../examplecloud_container.tf} | 0 .../examplecloud_container_import_with_identity.tf | 7 ------- 5 files changed, 10 insertions(+), 14 deletions(-) rename helper/resource/importstate/testdata/{writeable-config-file => 2}/examplecloud_container.tf (100%) rename helper/resource/importstate/testdata/{2/examplecloud_container_import.tf => 2_with_exact_import_config/examplecloud_container.tf} (100%) delete mode 100644 helper/resource/importstate/testdata/writeable-config-directory/examplecloud_container_import_with_identity.tf 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 f808af34..4675f0ed 100644 --- a/helper/resource/importstate/import_block_in_config_directory_test.go +++ b/helper/resource/importstate/import_block_in_config_directory_test.go @@ -16,7 +16,7 @@ import ( r "github.com/hashicorp/terraform-plugin-testing/helper/resource" ) -func TestImportBlock_InConfigDirectory_ConfigExactTrue(t *testing.T) { +func TestImportBlock_InConfigDirectory(t *testing.T) { t.Parallel() r.UnitTest(t, r.TestCase{ @@ -39,13 +39,13 @@ func TestImportBlock_InConfigDirectory_ConfigExactTrue(t *testing.T) { ImportState: true, ImportStateKind: r.ImportBlockWithID, ConfigDirectory: config.StaticDirectory(`testdata/2`), - ConfigExact: true, + ConfigExact: false, }, }, }) } -func TestImportBlock_InConfigDirectory(t *testing.T) { +func TestImportBlock_InConfigDirectory_ConfigExactTrue(t *testing.T) { t.Parallel() r.UnitTest(t, r.TestCase{ @@ -67,8 +67,11 @@ func TestImportBlock_InConfigDirectory(t *testing.T) { ResourceName: "examplecloud_container.test", ImportState: true, ImportStateKind: r.ImportBlockWithID, - ConfigDirectory: config.StaticDirectory(`testdata/writeable-config-directory`), - ConfigExact: false, + + // This content includes an import block with an ID so we will + // use the exact content + ConfigDirectory: config.StaticDirectory(`testdata/2_with_exact_import_config`), + ConfigExact: true, }, }, }) 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 757435d0..7926fbe2 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,7 @@ func TestImportBlock_InConfigFile(t *testing.T) { ResourceName: "examplecloud_container.test", ImportState: true, ImportStateKind: r.ImportBlockWithID, - ConfigFile: config.StaticFile(`testdata/writeable-config-file/examplecloud_container.tf`), + ConfigFile: config.StaticFile(`testdata/2/examplecloud_container.tf`), }, }, }) @@ -66,7 +66,7 @@ func TestImportBlock_WithResourceIdentity_InConfigFile(t *testing.T) { ResourceName: "examplecloud_container.test", ImportState: true, ImportStateKind: r.ImportBlockWithResourceIdentity, - ConfigFile: config.StaticFile(`testdata/writeable-config-file/examplecloud_container.tf`), + ConfigFile: config.StaticFile(`testdata/2/examplecloud_container.tf`), }, }, }) diff --git a/helper/resource/importstate/testdata/writeable-config-file/examplecloud_container.tf b/helper/resource/importstate/testdata/2/examplecloud_container.tf similarity index 100% rename from helper/resource/importstate/testdata/writeable-config-file/examplecloud_container.tf rename to helper/resource/importstate/testdata/2/examplecloud_container.tf diff --git a/helper/resource/importstate/testdata/2/examplecloud_container_import.tf b/helper/resource/importstate/testdata/2_with_exact_import_config/examplecloud_container.tf similarity index 100% rename from helper/resource/importstate/testdata/2/examplecloud_container_import.tf rename to helper/resource/importstate/testdata/2_with_exact_import_config/examplecloud_container.tf diff --git a/helper/resource/importstate/testdata/writeable-config-directory/examplecloud_container_import_with_identity.tf b/helper/resource/importstate/testdata/writeable-config-directory/examplecloud_container_import_with_identity.tf deleted file mode 100644 index ccfb698e..00000000 --- a/helper/resource/importstate/testdata/writeable-config-directory/examplecloud_container_import_with_identity.tf +++ /dev/null @@ -1,7 +0,0 @@ -# Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: MPL-2.0 - -resource "examplecloud_container" "test" { - name = "somevalue" - location = "westeurope" -} From 75caa2827578b6fac3db94041f5f78f744279b81 Mon Sep 17 00:00:00 2001 From: Baraa Basata Date: Fri, 2 May 2025 16:36:30 -0400 Subject: [PATCH 16/27] tidy --- .../importstate/import_block_in_config_directory_test.go | 1 - 1 file changed, 1 deletion(-) 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 4675f0ed..b1bb4b7d 100644 --- a/helper/resource/importstate/import_block_in_config_directory_test.go +++ b/helper/resource/importstate/import_block_in_config_directory_test.go @@ -39,7 +39,6 @@ func TestImportBlock_InConfigDirectory(t *testing.T) { ImportState: true, ImportStateKind: r.ImportBlockWithID, ConfigDirectory: config.StaticDirectory(`testdata/2`), - ConfigExact: false, }, }, }) From 2f36714073d3154e531d164b6668efd3e6f1c8d8 Mon Sep 17 00:00:00 2001 From: Baraa Basata Date: Fri, 2 May 2025 16:36:30 -0400 Subject: [PATCH 17/27] tidy --- .../importstate/import_block_in_config_file_test.go | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) 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 7926fbe2..3ee36c24 100644 --- a/helper/resource/importstate/import_block_in_config_file_test.go +++ b/helper/resource/importstate/import_block_in_config_file_test.go @@ -94,8 +94,11 @@ func TestImportBlock_InConfigFile_ConfigExactTrue(t *testing.T) { ResourceName: "examplecloud_container.test", ImportState: true, ImportStateKind: r.ImportBlockWithResourceIdentity, - ConfigFile: config.StaticFile(`testdata/examplecloud_container_import_with_identity.tf`), - ConfigExact: true, + + // This content includes an import block with an ID so we will + // use the exact content + ConfigFile: config.StaticFile(`testdata/examplecloud_container_import_with_identity.tf`), + ConfigExact: true, }, }, }) From 09fd5f05527e6dd35e2bea174a7cc32844731c91 Mon Sep 17 00:00:00 2001 From: Baraa Basata Date: Fri, 2 May 2025 16:36:30 -0400 Subject: [PATCH 18/27] tidy --- helper/resource/testing_new_import_state.go | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/helper/resource/testing_new_import_state.go b/helper/resource/testing_new_import_state.go index 86ef02ed..fdb63dfc 100644 --- a/helper/resource/testing_new_import_state.go +++ b/helper/resource/testing_new_import_state.go @@ -126,12 +126,11 @@ func testStepNewImportState(ctx context.Context, t testing.T, helper *plugintest case step.ConfigExact: break - default: - if kind.plannable() && kind.resourceIdentity() { - testStepConfig = appendImportBlockWithIdentity(testStepConfig, resourceName, priorIdentityValues) - } else if kind.plannable() { - testStepConfig = appendImportBlock(testStepConfig, resourceName, importId) - } + case kind.plannable() && kind.resourceIdentity(): + testStepConfig = appendImportBlockWithIdentity(testStepConfig, resourceName, priorIdentityValues) + + case kind.plannable(): + testStepConfig = appendImportBlock(testStepConfig, resourceName, importId) } if testStepConfig == nil { From 80943fce768a5bf5df5642a50884f8545276c737 Mon Sep 17 00:00:00 2001 From: Baraa Basata Date: Fri, 2 May 2025 16:36:30 -0400 Subject: [PATCH 19/27] tidy --- helper/resource/testing_new_import_state.go | 3 +-- internal/teststep/config.go | 2 +- internal/teststep/directory.go | 2 +- internal/teststep/file.go | 2 +- internal/teststep/string.go | 2 +- 5 files changed, 5 insertions(+), 6 deletions(-) diff --git a/helper/resource/testing_new_import_state.go b/helper/resource/testing_new_import_state.go index fdb63dfc..3ae94a82 100644 --- a/helper/resource/testing_new_import_state.go +++ b/helper/resource/testing_new_import_state.go @@ -428,7 +428,6 @@ func testImportCommand(ctx context.Context, t testing.T, workingDir *plugintest. func appendImportBlock(config teststep.Config, resourceName string, importID string) teststep.Config { return config.Append( - context.Background(), // TODO: remove fmt.Sprintf(``+"\n"+ `import {`+"\n"+ ` to = %s`+"\n"+ @@ -471,7 +470,7 @@ func appendImportBlockWithIdentity(config teststep.Config, resourceName string, configBuilder.WriteString(` }` + "\n") configBuilder.WriteString(`}` + "\n") - return config.Append(context.Background(), configBuilder.String()) + return config.Append(configBuilder.String()) } func importStatePreconditions(t testing.T, helper *plugintest.Helper, step TestStep) error { diff --git a/internal/teststep/config.go b/internal/teststep/config.go index be4ad0ce..91a708e2 100644 --- a/internal/teststep/config.go +++ b/internal/teststep/config.go @@ -45,7 +45,7 @@ type Config interface { HasProviderBlock(context.Context) (bool, error) HasTerraformBlock(context.Context) (bool, error) Write(context.Context, string) error - Append(context.Context, string) Config + Append(string) Config } // PrepareConfigurationRequest is used to simplify the generation of diff --git a/internal/teststep/directory.go b/internal/teststep/directory.go index 30bddd9e..979d61d6 100644 --- a/internal/teststep/directory.go +++ b/internal/teststep/directory.go @@ -101,7 +101,7 @@ func (c configurationDirectory) Write(ctx context.Context, dest string) error { return nil } -func (c configurationDirectory) Append(_ context.Context, config string) Config { +func (c configurationDirectory) Append(config string) Config { if c.generatedFiles == nil { c.generatedFiles = make(map[string]string) } diff --git a/internal/teststep/file.go b/internal/teststep/file.go index 669b761f..75ee6f7d 100644 --- a/internal/teststep/file.go +++ b/internal/teststep/file.go @@ -100,7 +100,7 @@ func (c configurationFile) Write(ctx context.Context, dest string) error { return nil } -func (c configurationFile) Append(_ context.Context, config string) Config { +func (c configurationFile) Append(config string) Config { return configurationFile{ file: c.file, appendedConfig: config, diff --git a/internal/teststep/string.go b/internal/teststep/string.go index 0d004250..39028682 100644 --- a/internal/teststep/string.go +++ b/internal/teststep/string.go @@ -61,7 +61,7 @@ func (c configurationString) Write(ctx context.Context, dest string) error { return nil } -func (c configurationString) Append(_ context.Context, config string) Config { +func (c configurationString) Append(config string) Config { return configurationString{ raw: strings.Join([]string{c.raw, config}, "\n"), } From de0a1a0ec47f2e308c497f72de5188474a44e337 Mon Sep 17 00:00:00 2001 From: Baraa Basata Date: Fri, 2 May 2025 16:36:30 -0400 Subject: [PATCH 20/27] tidy --- internal/teststep/directory.go | 18 ++++++++++-------- internal/teststep/directory_test.go | 10 +++++----- 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/internal/teststep/directory.go b/internal/teststep/directory.go index 979d61d6..e913be7d 100644 --- a/internal/teststep/directory.go +++ b/internal/teststep/directory.go @@ -15,8 +15,10 @@ var _ Config = configurationDirectory{} // not threadsafe type configurationDirectory struct { - directory string - generatedFiles map[string]string + directory string + + // appendedConfig is a map of filenames to content + appendedConfig map[string]string } // HasConfigurationFiles is used during validation to ensure that @@ -93,7 +95,7 @@ func (c configurationDirectory) Write(ctx context.Context, dest string) error { return err } - err = c.writeGeneratedFiles(dest) + err = c.writeAppendedConfig(dest) if err != nil { return err } @@ -102,19 +104,19 @@ func (c configurationDirectory) Write(ctx context.Context, dest string) error { } func (c configurationDirectory) Append(config string) Config { - if c.generatedFiles == nil { - c.generatedFiles = make(map[string]string) + if c.appendedConfig == nil { + c.appendedConfig = make(map[string]string) } checksum := crc32.Checksum([]byte(config), crc32.IEEETable) filename := fmt.Sprintf("terraform_plugin_test_%d.tf", checksum) - c.generatedFiles[filename] = config + c.appendedConfig[filename] = config return c } -func (c configurationDirectory) writeGeneratedFiles(dstPath string) error { - for filename, config := range c.generatedFiles { +func (c configurationDirectory) writeAppendedConfig(dstPath string) error { + for filename, config := range c.appendedConfig { outFilename := filepath.Join(dstPath, filename) err := os.WriteFile(outFilename, []byte(config), 0700) diff --git a/internal/teststep/directory_test.go b/internal/teststep/directory_test.go index f64419f2..cb88d214 100644 --- a/internal/teststep/directory_test.go +++ b/internal/teststep/directory_test.go @@ -607,7 +607,7 @@ func TestConfigurationDirectory_Write_AbsolutePath(t *testing.T) { } } -func TestConfigurationDirectory_Write_WithGeneratedFiles(t *testing.T) { +func TestConfigurationDirectory_Write_WithAppendedConfig(t *testing.T) { t.Parallel() testCases := map[string]struct { @@ -617,7 +617,7 @@ func TestConfigurationDirectory_Write_WithGeneratedFiles(t *testing.T) { "dir-single-file": { configDirectory: configurationDirectory{ directory: "testdata/random", - generatedFiles: map[string]string{ + appendedConfig: map[string]string{ "import.tf": `terraform {\nimport\n{\nto = satellite.the_moon\nid = "moon"\n}\n}\n`, }, }, @@ -667,11 +667,11 @@ func TestConfigurationDirectory_Write_WithGeneratedFiles(t *testing.T) { } } - generatedFiles := testCase.configDirectory.generatedFiles - for filename, expectedContent := range generatedFiles { + appendedConfigFiles := testCase.configDirectory.appendedConfig + for filename, expectedContent := range appendedConfigFiles { content, err := os.ReadFile(filepath.Join(tempDir, filename)) if err != nil { - t.Errorf("error reading generated file %s: %s", filename, err) + t.Errorf("error reading appended config file %s: %s", filename, err) } if diff := cmp.Diff([]byte(expectedContent), content); diff != "" { From 507b3b219ef0db45aaad5b45e4658916557b6e84 Mon Sep 17 00:00:00 2001 From: Baraa Basata Date: Fri, 2 May 2025 17:01:00 -0400 Subject: [PATCH 21/27] tidy --- .../resource/importstate/import_block_in_config_file_test.go | 4 ++-- ...xamplecloud_container_with_exact_import_config_with_id.tf} | 0 2 files changed, 2 insertions(+), 2 deletions(-) rename helper/resource/importstate/testdata/{examplecloud_container_import_with_identity.tf => examplecloud_container_with_exact_import_config_with_id.tf} (100%) 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 3ee36c24..491faa0a 100644 --- a/helper/resource/importstate/import_block_in_config_file_test.go +++ b/helper/resource/importstate/import_block_in_config_file_test.go @@ -93,11 +93,11 @@ func TestImportBlock_InConfigFile_ConfigExactTrue(t *testing.T) { { ResourceName: "examplecloud_container.test", ImportState: true, - ImportStateKind: r.ImportBlockWithResourceIdentity, + ImportStateKind: r.ImportBlockWithID, // This content includes an import block with an ID so we will // use the exact content - ConfigFile: config.StaticFile(`testdata/examplecloud_container_import_with_identity.tf`), + ConfigFile: config.StaticFile(`testdata/examplecloud_container_with_exact_import_config_with_id.tf`), ConfigExact: true, }, }, diff --git a/helper/resource/importstate/testdata/examplecloud_container_import_with_identity.tf b/helper/resource/importstate/testdata/examplecloud_container_with_exact_import_config_with_id.tf similarity index 100% rename from helper/resource/importstate/testdata/examplecloud_container_import_with_identity.tf rename to helper/resource/importstate/testdata/examplecloud_container_with_exact_import_config_with_id.tf From 1d4d6b76d8c498ca6bc40783f2233fd8245500f9 Mon Sep 17 00:00:00 2001 From: Baraa Basata Date: Mon, 5 May 2025 16:16:50 -0400 Subject: [PATCH 22/27] Add a test for appending to ConfigFile --- internal/teststep/file_test.go | 47 ++++++++++++++++++++++++++++++ internal/teststep/testdata/main.tf | 1 + 2 files changed, 48 insertions(+) create mode 100644 internal/teststep/testdata/main.tf diff --git a/internal/teststep/file_test.go b/internal/teststep/file_test.go index 118dd002..dc8a662c 100644 --- a/internal/teststep/file_test.go +++ b/internal/teststep/file_test.go @@ -11,6 +11,7 @@ import ( "testing" "github.com/google/go-cmp/cmp" + "github.com/hashicorp/terraform-plugin-testing/config" ) func TestConfigurationFile_HasProviderBlock(t *testing.T) { @@ -550,3 +551,49 @@ func TestConfigurationFile_Write_AbsolutePath(t *testing.T) { }) } } + +func TestConfigFile_Append(t *testing.T) { + t.Parallel() + + testCases := map[string]struct { + filename string + appendContent string + expectedContent string + }{ + "append content to a ConfigFile": { + filename: `testdata/main.tf`, // Contains `// Hello world` + appendContent: `terraform {}`, + expectedContent: "// Hello world\nterraform {}", + }, + } + + for name, testCase := range testCases { + t.Run(name, func(t *testing.T) { + t.Parallel() + + prepareConfigRequest := PrepareConfigurationRequest{ + File: func(config.TestStepConfigRequest) string { + return testCase.filename + }, + } + + teststepConfig := Configuration(prepareConfigRequest.Exec()) + teststepConfig = teststepConfig.Append(testCase.appendContent) + + tempdir := t.TempDir() + if err := teststepConfig.Write(context.Background(), tempdir); err != nil { + t.Fatalf("failed to write file: %s", err) + } + + got, err := os.ReadFile(filepath.Join(tempdir, filepath.Base(testCase.filename))) + if err != nil { + t.Fatalf("failed to read file: %s", err) + } + + gotS := string(got[:]) + if diff := cmp.Diff(testCase.expectedContent, gotS); diff != "" { + t.Errorf("expected %+v, got %+v", testCase.expectedContent, gotS) + } + }) + } +} diff --git a/internal/teststep/testdata/main.tf b/internal/teststep/testdata/main.tf new file mode 100644 index 00000000..a9e578c9 --- /dev/null +++ b/internal/teststep/testdata/main.tf @@ -0,0 +1 @@ +// Hello world From ba89faf8b1d453c7c8099e6f96e5b228f896cd7d Mon Sep 17 00:00:00 2001 From: Baraa Basata Date: Tue, 6 May 2025 12:11:51 -0400 Subject: [PATCH 23/27] Fix testdata --- ...examplecloud_container_with_exact_import_config_with_id.tf | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/helper/resource/importstate/testdata/examplecloud_container_with_exact_import_config_with_id.tf b/helper/resource/importstate/testdata/examplecloud_container_with_exact_import_config_with_id.tf index 9412afb9..f7e9411f 100644 --- a/helper/resource/importstate/testdata/examplecloud_container_with_exact_import_config_with_id.tf +++ b/helper/resource/importstate/testdata/examplecloud_container_with_exact_import_config_with_id.tf @@ -8,7 +8,5 @@ resource "examplecloud_container" "test" { import { to = examplecloud_container.test - identity = { - id = "examplecloud_container.test" - } + id = "examplecloud_container.test" } From 5f9a0d0032d11f96a22e817ea59273428eed1346 Mon Sep 17 00:00:00 2001 From: Baraa Basata Date: Tue, 6 May 2025 12:16:33 -0400 Subject: [PATCH 24/27] Add changelog entry --- .changes/unreleased/NOTES-20250506-121618.yaml | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changes/unreleased/NOTES-20250506-121618.yaml diff --git a/.changes/unreleased/NOTES-20250506-121618.yaml b/.changes/unreleased/NOTES-20250506-121618.yaml new file mode 100644 index 00000000..028c3fa5 --- /dev/null +++ b/.changes/unreleased/NOTES-20250506-121618.yaml @@ -0,0 +1,5 @@ +kind: NOTES +body: 'ImportState: extend auto-generated import blocks to work with `ConfigFile` and `ConfigDirectory`; adds `ConfigExact` flag to opt out' +time: 2025-05-06T12:16:18.375025-04:00 +custom: + Issue: "494" From 956450d21d790f433ca8c42aed492b7313d9be9c Mon Sep 17 00:00:00 2001 From: Baraa Basata Date: Tue, 6 May 2025 12:19:00 -0400 Subject: [PATCH 25/27] copywrite --- internal/teststep/testdata/main.tf | 3 +++ 1 file changed, 3 insertions(+) diff --git a/internal/teststep/testdata/main.tf b/internal/teststep/testdata/main.tf index a9e578c9..ba356816 100644 --- a/internal/teststep/testdata/main.tf +++ b/internal/teststep/testdata/main.tf @@ -1 +1,4 @@ +# Copyright (c) HashiCorp, Inc. +# SPDX-License-Identifier: MPL-2.0 + // Hello world From b74081a569f12195e30bfb5a6fd02c89c36d6431 Mon Sep 17 00:00:00 2001 From: Baraa Basata Date: Tue, 6 May 2025 14:09:49 -0400 Subject: [PATCH 26/27] Update test expectation --- internal/teststep/file_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/teststep/file_test.go b/internal/teststep/file_test.go index dc8a662c..b6f89bed 100644 --- a/internal/teststep/file_test.go +++ b/internal/teststep/file_test.go @@ -563,7 +563,7 @@ func TestConfigFile_Append(t *testing.T) { "append content to a ConfigFile": { filename: `testdata/main.tf`, // Contains `// Hello world` appendContent: `terraform {}`, - expectedContent: "// Hello world\nterraform {}", + expectedContent: "# Copyright (c) HashiCorp, Inc.\n# SPDX-License-Identifier: MPL-2.0\n\n// Hello world" + "\n" + "terraform {}", }, } From 712b939733de655d3ded173d93e09ce2c2f54648 Mon Sep 17 00:00:00 2001 From: Baraa Basata Date: Wed, 7 May 2025 10:24:02 -0400 Subject: [PATCH 27/27] Rename to ImportStateConfigExact and tidy comment --- .../import_block_as_first_step_test.go | 2 +- .../import_block_in_config_directory_test.go | 4 +-- .../import_block_in_config_file_test.go | 4 +-- .../importstate/import_block_with_id_test.go | 28 +++++++++---------- helper/resource/testing.go | 4 +-- helper/resource/testing_new_import_state.go | 2 +- internal/teststep/directory.go | 1 - 7 files changed, 22 insertions(+), 23 deletions(-) diff --git a/helper/resource/importstate/import_block_as_first_step_test.go b/helper/resource/importstate/import_block_as_first_step_test.go index a3f77fac..e7dacef9 100644 --- a/helper/resource/importstate/import_block_as_first_step_test.go +++ b/helper/resource/importstate/import_block_as_first_step_test.go @@ -48,7 +48,7 @@ func TestImportBlock_AsFirstStep(t *testing.T) { id = "westeurope/somevalue" } `, - ConfigExact: true, + ImportStateConfigExact: true, ImportPlanChecks: r.ImportPlanChecks{ PreApply: []plancheck.PlanCheck{ plancheck.ExpectResourceAction("examplecloud_container.test", plancheck.ResourceActionNoop), 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 b1bb4b7d..cf24a024 100644 --- a/helper/resource/importstate/import_block_in_config_directory_test.go +++ b/helper/resource/importstate/import_block_in_config_directory_test.go @@ -69,8 +69,8 @@ func TestImportBlock_InConfigDirectory_ConfigExactTrue(t *testing.T) { // This content includes an import block with an ID so we will // use the exact content - ConfigDirectory: config.StaticDirectory(`testdata/2_with_exact_import_config`), - ConfigExact: true, + ConfigDirectory: config.StaticDirectory(`testdata/2_with_exact_import_config`), + ImportStateConfigExact: true, }, }, }) 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 491faa0a..db762f2d 100644 --- a/helper/resource/importstate/import_block_in_config_file_test.go +++ b/helper/resource/importstate/import_block_in_config_file_test.go @@ -97,8 +97,8 @@ func TestImportBlock_InConfigFile_ConfigExactTrue(t *testing.T) { // This content includes an import block with an ID so we will // use the exact content - ConfigFile: config.StaticFile(`testdata/examplecloud_container_with_exact_import_config_with_id.tf`), - ConfigExact: true, + ConfigFile: config.StaticFile(`testdata/examplecloud_container_with_exact_import_config_with_id.tf`), + ImportStateConfigExact: true, }, }, }) diff --git a/helper/resource/importstate/import_block_with_id_test.go b/helper/resource/importstate/import_block_with_id_test.go index 9a14577b..c11754a6 100644 --- a/helper/resource/importstate/import_block_with_id_test.go +++ b/helper/resource/importstate/import_block_with_id_test.go @@ -89,11 +89,11 @@ func TestImportBlock_WithID_ExpectError(t *testing.T) { id = "westeurope/somevalue" } `, - ConfigExact: true, - ResourceName: "examplecloud_container.test", - ImportState: true, - ImportStateKind: r.ImportBlockWithID, - ExpectError: regexp.MustCompile(`importing resource examplecloud_container.test: expected a no-op import operation, got.*\["update"\] action with plan(.?)`), + ResourceName: "examplecloud_container.test", + ImportState: true, + ImportStateKind: r.ImportBlockWithID, + ImportStateConfigExact: true, + ExpectError: regexp.MustCompile(`importing resource examplecloud_container.test: expected a no-op import operation, got.*\["update"\] action with plan(.?)`), }, }, }) @@ -296,10 +296,10 @@ func TestImportBlock_WithID_WithBlankOptionalAttribute_GeneratesCorrectPlan(t *t id = "sometestid" }`, - ConfigExact: true, - ResourceName: "examplecloud_container.test", - ImportState: true, - ImportStateKind: r.ImportBlockWithID, + ResourceName: "examplecloud_container.test", + ImportState: true, + ImportStateKind: r.ImportBlockWithID, + ImportStateConfigExact: true, }, }, }) @@ -418,11 +418,11 @@ import { Config: config, }, { - ImportState: true, - ImportStateKind: r.ImportBlockWithID, - Config: configWithImportBlock, - ConfigExact: true, - ResourceName: "random_string.mystery_message", + ImportState: true, + ImportStateKind: r.ImportBlockWithID, + ImportStateConfigExact: true, + Config: configWithImportBlock, + ResourceName: "random_string.mystery_message", ImportPlanChecks: r.ImportPlanChecks{ PreApply: []plancheck.PlanCheck{ plancheck.ExpectKnownValue( diff --git a/helper/resource/testing.go b/helper/resource/testing.go index 367794b3..fab58baa 100644 --- a/helper/resource/testing.go +++ b/helper/resource/testing.go @@ -576,7 +576,7 @@ type TestStep struct { // otherwise an error will be returned. ConfigFile config.TestStepConfigFunc - // ConfigExact indicates that the test framework should use the exact + // ImportStateConfigExact indicates that the test framework should use the exact // content of the Config, ConfigFile, or ConfigDirectory inputs and should // not modify it at test run time. // @@ -584,7 +584,7 @@ type TestStep struct { // specific kinds of configuration, such as import blocks, and append them // to the given Config, ConfigFile, or ConfigDirectory inputs. Using this // default improves test readability and removes duplication of setup. - ConfigExact bool + ImportStateConfigExact bool // ConfigVariables is a map defining variables for use in conjunction // with Terraform configuration. If this map is populated then it diff --git a/helper/resource/testing_new_import_state.go b/helper/resource/testing_new_import_state.go index 3ae94a82..dae85825 100644 --- a/helper/resource/testing_new_import_state.go +++ b/helper/resource/testing_new_import_state.go @@ -123,7 +123,7 @@ func testStepNewImportState(ctx context.Context, t testing.T, helper *plugintest }.Exec()) switch { - case step.ConfigExact: + case step.ImportStateConfigExact: break case kind.plannable() && kind.resourceIdentity(): diff --git a/internal/teststep/directory.go b/internal/teststep/directory.go index e913be7d..67ecc5cc 100644 --- a/internal/teststep/directory.go +++ b/internal/teststep/directory.go @@ -13,7 +13,6 @@ import ( var _ Config = configurationDirectory{} -// not threadsafe type configurationDirectory struct { directory string