Skip to content
Closed
Show file tree
Hide file tree
Changes from 26 commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
2e6c321
Prepare to move test to a directory
bbasata Mar 20, 2025
288ec26
Move test to import_test package
bbasata Mar 20, 2025
e924715
Extract testprovider resource from test
bbasata Mar 20, 2025
4b76aba
More test provider extraction
bbasata Mar 20, 2025
f7076a9
Add a test expecting fail when plannable import is not supported
bbasata Mar 20, 2025
6865074
importstate: a working example of ImportState as the first TestStep
bbasata Mar 21, 2025
70f740d
importstate: a working example of ImportBlockWithId as the first Test…
bbasata Mar 21, 2025
d8f5ccb
make generate
bbasata Mar 24, 2025
5e5f6d6
Merge remote-tracking branch 'origin/main' into import-as-first-test-…
bbasata Mar 24, 2025
0872e07
Use PlanChecks
bbasata Mar 24, 2025
5d6bf83
Simpler test names
bbasata Mar 24, 2025
f45d8fe
Tidy comment
bbasata Mar 24, 2025
a36cde2
wip
bbasata Mar 24, 2025
3b822d6
fixup! wip
bbasata Mar 24, 2025
3134be2
Extract functions
bbasata Mar 24, 2025
99f1fae
Add tests for import block in ConfigFile and ConfigDirectory
bbasata Mar 24, 2025
42f36b7
Mark test helper function
bbasata Mar 24, 2025
024ac49
minimize diff
bbasata Mar 24, 2025
bd29ab0
Extract requireNoopResourceAction
bbasata Mar 24, 2025
c0fd026
Fail ImportStateVerify if no new resources are imported
bbasata Mar 24, 2025
b0a502e
ImportPlanVerify
bbasata Mar 25, 2025
4cf6a87
Use ImportPlanVerify
bbasata Mar 25, 2025
f085ea6
fixup! Use ImportPlanVerify
bbasata Mar 25, 2025
eb4679f
fixup! fixup! Use ImportPlanVerify
bbasata Mar 25, 2025
3a7afd5
fixup! fixup! fixup! Use ImportPlanVerify
bbasata Mar 25, 2025
f5f93c1
fixup! fixup! fixup! fixup! Use ImportPlanVerify
bbasata Mar 25, 2025
58ec6b8
fixup! fixup! fixup! fixup! fixup! Use ImportPlanVerify
bbasata Mar 26, 2025
9643933
Update helper/resource/testing.go
bbasata Mar 27, 2025
f9f6ac4
Update helper/resource/testing_new_import_state.go
bbasata Mar 27, 2025
2b23914
Merge branch 'main' into import-compare-plan-to-previous-state
bbasata Mar 31, 2025
c3a6290
helper/resource: easy access to state in tfjson.State form
bbasata Mar 31, 2025
b0abb5b
Merge remote-tracking branch 'origin/get-state-json' into import-comp…
bbasata Mar 31, 2025
8242c05
Use tfjson.State
bbasata Mar 31, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 56 additions & 0 deletions helper/resource/importstate/import_block_as_first_step_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0

package importstate_test

import (
"testing"

"github.com/hashicorp/terraform-plugin-go/tfprotov6"

"github.com/hashicorp/terraform-plugin-testing/internal/testing/testprovider"
"github.com/hashicorp/terraform-plugin-testing/internal/testing/testsdk/providerserver"
"github.com/hashicorp/terraform-plugin-testing/knownvalue"
"github.com/hashicorp/terraform-plugin-testing/plancheck"
"github.com/hashicorp/terraform-plugin-testing/tfjsonpath"
"github.com/hashicorp/terraform-plugin-testing/tfversion"

r "github.com/hashicorp/terraform-plugin-testing/helper/resource"
)

func Test_ImportBlock_AsFirstStep(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{
{
ResourceName: "examplecloud_container.test",
ImportStateId: "examplecloud_container.test",
ImportState: true,
ImportStateKind: r.ImportBlockWithID,
Config: `resource "examplecloud_container" "test" {
name = "somevalue"
location = "westeurope"
}`,
ImportPlanChecks: r.ImportPlanChecks{
PreApply: []plancheck.PlanCheck{
plancheck.ExpectResourceAction("examplecloud_container.test", plancheck.ResourceActionNoop),
plancheck.ExpectKnownValue("examplecloud_container.test", tfjsonpath.New("id"), knownvalue.StringExact("westeurope/somevalue")),
plancheck.ExpectKnownValue("examplecloud_container.test", tfjsonpath.New("name"), knownvalue.StringExact("somevalue")),
plancheck.ExpectKnownValue("examplecloud_container.test", tfjsonpath.New("location"), knownvalue.StringExact("westeurope")),
},
},
},
},
})
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0

package importstate_test

import (
"testing"

"github.com/hashicorp/terraform-plugin-go/tfprotov6"

"github.com/hashicorp/terraform-plugin-testing/config"
"github.com/hashicorp/terraform-plugin-testing/internal/testing/testprovider"
"github.com/hashicorp/terraform-plugin-testing/internal/testing/testsdk/providerserver"
"github.com/hashicorp/terraform-plugin-testing/tfversion"

r "github.com/hashicorp/terraform-plugin-testing/helper/resource"
)

func Test_ImportBlock_InConfigDirectory(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: func(config.TestStepConfigRequest) string {
return `testdata/1`
},
},
{
ResourceName: "examplecloud_container.test",
ImportState: true,
ImportStateKind: r.ImportBlockWithID,
ImportPlanVerify: true,
ConfigDirectory: func(config.TestStepConfigRequest) string {
return `testdata/2`
},
},
},
})
}
50 changes: 50 additions & 0 deletions helper/resource/importstate/import_block_in_config_file_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0

package importstate_test

import (
"testing"

"github.com/hashicorp/terraform-plugin-go/tfprotov6"

"github.com/hashicorp/terraform-plugin-testing/config"
"github.com/hashicorp/terraform-plugin-testing/internal/testing/testprovider"
"github.com/hashicorp/terraform-plugin-testing/internal/testing/testsdk/providerserver"
"github.com/hashicorp/terraform-plugin-testing/tfversion"

r "github.com/hashicorp/terraform-plugin-testing/helper/resource"
)

func Test_ImportBlock_InConfigFile(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: func(config.TestStepConfigRequest) string {
return `testdata/1/examplecloud_container.tf`
},
},
{
ResourceName: "examplecloud_container.test",
ImportState: true,
ImportStateKind: r.ImportBlockWithID,
ImportPlanVerify: true,
ConfigFile: func(config.TestStepConfigRequest) string {
return `testdata/2/examplecloud_container_import.tf`
},
},
},
})
}
48 changes: 48 additions & 0 deletions helper/resource/importstate/import_block_verify_plan_test.go
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: I'd love to see a negative test here as well, like one where the follow-up plan has changes.

Might need to do some awkwardness to create that "inconsistency" without having a remote system, especially since the end of test step 1 will refresh. In the past I've used the provider factories on each test step to inject the differences, which is a potential option: https://github.com/hashicorp/terraform-provider-corner/blob/52e22f4ee878680727ff68a2e44967b496242a76/internal/protocolv6provider/writeonly_datacheck_test.go#L182-L204

Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0

package importstate_test

import (
"testing"

"github.com/hashicorp/terraform-plugin-go/tfprotov6"

"github.com/hashicorp/terraform-plugin-testing/internal/testing/testprovider"
"github.com/hashicorp/terraform-plugin-testing/internal/testing/testsdk/providerserver"
"github.com/hashicorp/terraform-plugin-testing/tfversion"

r "github.com/hashicorp/terraform-plugin-testing/helper/resource"
)

func Test_ImportBlock_VerifyPlan(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{
{
Config: `
resource "examplecloud_container" "test" {
location = "westeurope"
name = "somevalue"
}`,
},
{
ResourceName: "examplecloud_container.test",
ImportState: true,
ImportStateKind: r.ImportBlockWithID,
ImportPlanVerify: true,
},
},
})
}
52 changes: 29 additions & 23 deletions helper/resource/importstate/import_block_with_id_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,12 @@ import (
r "github.com/hashicorp/terraform-plugin-testing/helper/resource"
)

func TestTest_TestStep_ImportBlockId(t *testing.T) {
func Test_TestStep_ImportBlockId(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
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{
Expand All @@ -44,10 +44,9 @@ func TestTest_TestStep_ImportBlockId(t *testing.T) {
}`,
},
{
ResourceName: "examplecloud_container.test",
ImportState: true,
ImportStateKind: r.ImportBlockWithId,
ImportStateVerify: true,
ResourceName: "examplecloud_container.test",
ImportState: true,
ImportStateKind: r.ImportBlockWithID,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Is there a reason we don't want to use ImportStateVerify here?

},
},
})
Expand All @@ -58,7 +57,7 @@ func TestTest_TestStep_ImportBlockId_ExpectError(t *testing.T) {

r.UnitTest(t, r.TestCase{
TerraformVersionChecks: []tfversion.TerraformVersionCheck{
tfversion.SkipBelow(tfversion.Version1_5_0), // ImportBlockWithId requires Terraform 1.5.0 or later
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{
Expand All @@ -81,11 +80,10 @@ func TestTest_TestStep_ImportBlockId_ExpectError(t *testing.T) {
location = "eastus"
name = "somevalue"
}`,
ResourceName: "examplecloud_container.test",
ImportState: true,
ImportStateKind: r.ImportBlockWithId,
ImportStateVerify: true,
ExpectError: regexp.MustCompile(`importing resource examplecloud_container.test should be a no-op, but got action update with plan(.?)`),
ResourceName: "examplecloud_container.test",
ImportState: true,
ImportStateKind: r.ImportBlockWithID,
ExpectError: regexp.MustCompile(`importing resource examplecloud_container.test: expected a no-op resource action, got "update" action with plan(.?)`),
},
},
})
Expand Down Expand Up @@ -120,11 +118,10 @@ func TestTest_TestStep_ImportBlockId_FailWhenPlannableImportIsNotSupported(t *te
location = "eastus"
name = "somevalue"
}`,
ResourceName: "examplecloud_container.test",
ImportState: true,
ImportStateKind: r.ImportBlockWithId,
ImportStateVerify: true,
ExpectError: regexp.MustCompile(`Terraform 1.5.0`),
ResourceName: "examplecloud_container.test",
ImportState: true,
ImportStateKind: r.ImportBlockWithID,
ExpectError: regexp.MustCompile(`Terraform 1.5.0`),
},
},
})
Expand All @@ -135,7 +132,7 @@ func TestTest_TestStep_ImportBlockId_SkipDataSourceState(t *testing.T) {

r.UnitTest(t, r.TestCase{
TerraformVersionChecks: []tfversion.TerraformVersionCheck{
tfversion.SkipBelow(tfversion.Version1_5_0), // ImportBlockWithId requires Terraform 1.5.0 or later
tfversion.SkipBelow(tfversion.Version1_5_0), // ImportBlockWithID requires Terraform 1.5.0 or later

},
ProtoV6ProviderFactories: map[string]func() (tfprotov6.ProviderServer, error){
Expand All @@ -161,7 +158,7 @@ func TestTest_TestStep_ImportBlockId_SkipDataSourceState(t *testing.T) {
{
ResourceName: "examplecloud_thing.test",
ImportState: true,
ImportStateKind: r.ImportBlockWithId,
ImportStateKind: r.ImportBlockWithID,
ImportStateCheck: func(is []*terraform.InstanceState) error {
if len(is) > 1 {
return fmt.Errorf("expected 1 state, got: %d", len(is))
Expand Down Expand Up @@ -200,11 +197,16 @@ func TestTest_TestStep_ImportBlockId_ImportStateVerifyIgnore_Real_Example(t *tes
I also need to omit the `password` in the import config, otherwise the value in the config is used when importing the
with an import block and the test ends up passing regardless of whether `ImportStateVerifyIgnore` has been specified or not
*/

// In prerelease, we are choosing that ImportBlockWithID will not perform an apply, so it will not produce a new state,
// and there is no new state for ImportStateVerify to do anything meaningful with.
Comment on lines +204 to +205
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Are we planning on revisiting this decision later? If so, maybe a TODO prefix here (I know I'll forget what the original intention was of this comment 😆)

Same question for the other test below

t.Skip()

t.Parallel()

r.UnitTest(t, r.TestCase{
TerraformVersionChecks: []tfversion.TerraformVersionCheck{
tfversion.SkipBelow(tfversion.Version1_5_0), // ImportBlockWithId requires Terraform 1.5.0 or later
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{
Expand Down Expand Up @@ -292,7 +294,7 @@ func TestTest_TestStep_ImportBlockId_ImportStateVerifyIgnore_Real_Example(t *tes
}`,
ResourceName: "examplecloud_container.test",
ImportState: true,
ImportStateKind: r.ImportBlockWithId,
ImportStateKind: r.ImportBlockWithID,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"password"},
},
Expand All @@ -301,11 +303,15 @@ func TestTest_TestStep_ImportBlockId_ImportStateVerifyIgnore_Real_Example(t *tes
}

func TestTest_TestStep_ImportBlockId_ImportStateVerifyIgnore(t *testing.T) {
// In prerelease, we are choosing that ImportBlockWithID will not perform an apply, so it will not produce a new state,
// and there is no new state for ImportStateVerify to do anything meaningful with.
t.Skip()

t.Parallel()

r.UnitTest(t, r.TestCase{
TerraformVersionChecks: []tfversion.TerraformVersionCheck{
tfversion.SkipBelow(tfversion.Version1_5_0), // ImportBlockWithId requires Terraform 1.5.0 or later
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{
Expand Down Expand Up @@ -377,7 +383,7 @@ func TestTest_TestStep_ImportBlockId_ImportStateVerifyIgnore(t *testing.T) {
{
ResourceName: "examplecloud_container.test",
ImportState: true,
ImportStateKind: r.ImportBlockWithId,
ImportStateKind: r.ImportBlockWithID,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"password"},
},
Expand Down
Loading
Loading