Skip to content

Commit c4be868

Browse files
bbasataaustinvalle
andauthored
Add tests using ConfigFile and ConfigDirectory with plannable import (#465)
* Prepare to move test to a directory * Move test to import_test package * Extract testprovider resource from test * More test provider extraction * Add a test expecting fail when plannable import is not supported * importstate: a working example of ImportState as the first TestStep * importstate: a working example of ImportBlockWithId as the first TestStep * make generate * Use PlanChecks * Simpler test names * Tidy comment * wip * fixup! wip * Extract functions * Add tests for import block in ConfigFile and ConfigDirectory * Mark test helper function * minimize diff * Update helper/resource/testing.go Co-authored-by: Austin Valle <[email protected]> * Use Static{File,Directory} helper functions --------- Co-authored-by: Austin Valle <[email protected]>
1 parent e010ab2 commit c4be868

9 files changed

+218
-94
lines changed

helper/resource/importstate/import_block_as_first_step_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ func Test_ImportBlock_AsFirstStep(t *testing.T) {
2323

2424
r.UnitTest(t, r.TestCase{
2525
TerraformVersionChecks: []tfversion.TerraformVersionCheck{
26-
tfversion.SkipBelow(tfversion.Version1_5_0), // ImportBlockWithId requires Terraform 1.5.0 or later
26+
tfversion.SkipBelow(tfversion.Version1_5_0), // ImportBlockWithID requires Terraform 1.5.0 or later
2727
},
2828
ProtoV6ProviderFactories: map[string]func() (tfprotov6.ProviderServer, error){
2929
"examplecloud": providerserver.NewProviderServer(testprovider.Provider{
@@ -37,7 +37,7 @@ func Test_ImportBlock_AsFirstStep(t *testing.T) {
3737
ResourceName: "examplecloud_container.test",
3838
ImportStateId: "examplecloud_container.test",
3939
ImportState: true,
40-
ImportStateKind: r.ImportBlockWithId,
40+
ImportStateKind: r.ImportBlockWithID,
4141
// ImportStateVerify: true,
4242
Config: `resource "examplecloud_container" "test" {
4343
name = "somevalue"
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
// Copyright (c) HashiCorp, Inc.
2+
// SPDX-License-Identifier: MPL-2.0
3+
4+
package importstate_test
5+
6+
import (
7+
"testing"
8+
9+
"github.com/hashicorp/terraform-plugin-go/tfprotov6"
10+
11+
"github.com/hashicorp/terraform-plugin-testing/config"
12+
"github.com/hashicorp/terraform-plugin-testing/internal/testing/testprovider"
13+
"github.com/hashicorp/terraform-plugin-testing/internal/testing/testsdk/providerserver"
14+
"github.com/hashicorp/terraform-plugin-testing/tfversion"
15+
16+
r "github.com/hashicorp/terraform-plugin-testing/helper/resource"
17+
)
18+
19+
func Test_ImportBlock_InConfigDirectory(t *testing.T) {
20+
t.Parallel()
21+
22+
r.UnitTest(t, r.TestCase{
23+
TerraformVersionChecks: []tfversion.TerraformVersionCheck{
24+
tfversion.SkipBelow(tfversion.Version1_5_0), // ImportBlockWithID requires Terraform 1.5.0 or later
25+
},
26+
ProtoV6ProviderFactories: map[string]func() (tfprotov6.ProviderServer, error){
27+
"examplecloud": providerserver.NewProviderServer(testprovider.Provider{
28+
Resources: map[string]testprovider.Resource{
29+
"examplecloud_container": examplecloudResource(),
30+
},
31+
}),
32+
},
33+
Steps: []r.TestStep{
34+
{
35+
ConfigDirectory: config.StaticDirectory(`testdata/1`),
36+
},
37+
{
38+
ResourceName: "examplecloud_container.test",
39+
ImportState: true,
40+
ImportStateKind: r.ImportBlockWithID,
41+
ImportStateVerify: true,
42+
ConfigDirectory: config.StaticDirectory(`testdata/2`),
43+
},
44+
},
45+
})
46+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
// Copyright (c) HashiCorp, Inc.
2+
// SPDX-License-Identifier: MPL-2.0
3+
4+
package importstate_test
5+
6+
import (
7+
"testing"
8+
9+
"github.com/hashicorp/terraform-plugin-go/tfprotov6"
10+
11+
"github.com/hashicorp/terraform-plugin-testing/config"
12+
"github.com/hashicorp/terraform-plugin-testing/internal/testing/testprovider"
13+
"github.com/hashicorp/terraform-plugin-testing/internal/testing/testsdk/providerserver"
14+
"github.com/hashicorp/terraform-plugin-testing/tfversion"
15+
16+
r "github.com/hashicorp/terraform-plugin-testing/helper/resource"
17+
)
18+
19+
func Test_ImportBlock_InConfigFile(t *testing.T) {
20+
t.Parallel()
21+
22+
r.UnitTest(t, r.TestCase{
23+
TerraformVersionChecks: []tfversion.TerraformVersionCheck{
24+
tfversion.SkipBelow(tfversion.Version1_5_0), // ImportBlockWithID requires Terraform 1.5.0 or later
25+
},
26+
ProtoV6ProviderFactories: map[string]func() (tfprotov6.ProviderServer, error){
27+
"examplecloud": providerserver.NewProviderServer(testprovider.Provider{
28+
Resources: map[string]testprovider.Resource{
29+
"examplecloud_container": examplecloudResource(),
30+
},
31+
}),
32+
},
33+
Steps: []r.TestStep{
34+
{
35+
ConfigFile: config.StaticFile(`testdata/1/examplecloud_container.tf`),
36+
},
37+
{
38+
ResourceName: "examplecloud_container.test",
39+
ImportState: true,
40+
ImportStateKind: r.ImportBlockWithID,
41+
ImportStateVerify: true,
42+
ConfigFile: config.StaticFile(`testdata/2/examplecloud_container_import.tf`),
43+
},
44+
},
45+
})
46+
}

helper/resource/importstate/import_block_with_id_test.go

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ func Test_TestStep_ImportBlockId(t *testing.T) {
2626

2727
r.UnitTest(t, r.TestCase{
2828
TerraformVersionChecks: []tfversion.TerraformVersionCheck{
29-
tfversion.SkipBelow(tfversion.Version1_5_0), // ImportBlockWithId requires Terraform 1.5.0 or later
29+
tfversion.SkipBelow(tfversion.Version1_5_0), // ImportBlockWithID requires Terraform 1.5.0 or later
3030
},
3131
ProtoV6ProviderFactories: map[string]func() (tfprotov6.ProviderServer, error){
3232
"examplecloud": providerserver.NewProviderServer(testprovider.Provider{
@@ -46,7 +46,7 @@ func Test_TestStep_ImportBlockId(t *testing.T) {
4646
{
4747
ResourceName: "examplecloud_container.test",
4848
ImportState: true,
49-
ImportStateKind: r.ImportBlockWithId,
49+
ImportStateKind: r.ImportBlockWithID,
5050
ImportStateVerify: true,
5151
},
5252
},
@@ -58,7 +58,7 @@ func TestTest_TestStep_ImportBlockId_ExpectError(t *testing.T) {
5858

5959
r.UnitTest(t, r.TestCase{
6060
TerraformVersionChecks: []tfversion.TerraformVersionCheck{
61-
tfversion.SkipBelow(tfversion.Version1_5_0), // ImportBlockWithId requires Terraform 1.5.0 or later
61+
tfversion.SkipBelow(tfversion.Version1_5_0), // ImportBlockWithID requires Terraform 1.5.0 or later
6262
},
6363
ProtoV6ProviderFactories: map[string]func() (tfprotov6.ProviderServer, error){
6464
"examplecloud": providerserver.NewProviderServer(testprovider.Provider{
@@ -83,9 +83,9 @@ func TestTest_TestStep_ImportBlockId_ExpectError(t *testing.T) {
8383
}`,
8484
ResourceName: "examplecloud_container.test",
8585
ImportState: true,
86-
ImportStateKind: r.ImportBlockWithId,
86+
ImportStateKind: r.ImportBlockWithID,
8787
ImportStateVerify: true,
88-
ExpectError: regexp.MustCompile(`importing resource examplecloud_container.test should be a no-op, but got action update with plan(.?)`),
88+
ExpectError: regexp.MustCompile(`importing resource examplecloud_container.test: expected a no-op resource action, got "update" action with plan(.?)`),
8989
},
9090
},
9191
})
@@ -122,7 +122,7 @@ func TestTest_TestStep_ImportBlockId_FailWhenPlannableImportIsNotSupported(t *te
122122
}`,
123123
ResourceName: "examplecloud_container.test",
124124
ImportState: true,
125-
ImportStateKind: r.ImportBlockWithId,
125+
ImportStateKind: r.ImportBlockWithID,
126126
ImportStateVerify: true,
127127
ExpectError: regexp.MustCompile(`Terraform 1.5.0`),
128128
},
@@ -135,7 +135,7 @@ func TestTest_TestStep_ImportBlockId_SkipDataSourceState(t *testing.T) {
135135

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

140140
},
141141
ProtoV6ProviderFactories: map[string]func() (tfprotov6.ProviderServer, error){
@@ -161,7 +161,7 @@ func TestTest_TestStep_ImportBlockId_SkipDataSourceState(t *testing.T) {
161161
{
162162
ResourceName: "examplecloud_thing.test",
163163
ImportState: true,
164-
ImportStateKind: r.ImportBlockWithId,
164+
ImportStateKind: r.ImportBlockWithID,
165165
ImportStateCheck: func(is []*terraform.InstanceState) error {
166166
if len(is) > 1 {
167167
return fmt.Errorf("expected 1 state, got: %d", len(is))
@@ -204,7 +204,7 @@ func TestTest_TestStep_ImportBlockId_ImportStateVerifyIgnore_Real_Example(t *tes
204204

205205
r.UnitTest(t, r.TestCase{
206206
TerraformVersionChecks: []tfversion.TerraformVersionCheck{
207-
tfversion.SkipBelow(tfversion.Version1_5_0), // ImportBlockWithId requires Terraform 1.5.0 or later
207+
tfversion.SkipBelow(tfversion.Version1_5_0), // ImportBlockWithID requires Terraform 1.5.0 or later
208208
},
209209
ProtoV6ProviderFactories: map[string]func() (tfprotov6.ProviderServer, error){
210210
"examplecloud": providerserver.NewProviderServer(testprovider.Provider{
@@ -292,7 +292,7 @@ func TestTest_TestStep_ImportBlockId_ImportStateVerifyIgnore_Real_Example(t *tes
292292
}`,
293293
ResourceName: "examplecloud_container.test",
294294
ImportState: true,
295-
ImportStateKind: r.ImportBlockWithId,
295+
ImportStateKind: r.ImportBlockWithID,
296296
ImportStateVerify: true,
297297
ImportStateVerifyIgnore: []string{"password"},
298298
},
@@ -305,7 +305,7 @@ func TestTest_TestStep_ImportBlockId_ImportStateVerifyIgnore(t *testing.T) {
305305

306306
r.UnitTest(t, r.TestCase{
307307
TerraformVersionChecks: []tfversion.TerraformVersionCheck{
308-
tfversion.SkipBelow(tfversion.Version1_5_0), // ImportBlockWithId requires Terraform 1.5.0 or later
308+
tfversion.SkipBelow(tfversion.Version1_5_0), // ImportBlockWithID requires Terraform 1.5.0 or later
309309
},
310310
ProtoV6ProviderFactories: map[string]func() (tfprotov6.ProviderServer, error){
311311
"examplecloud": providerserver.NewProviderServer(testprovider.Provider{
@@ -377,7 +377,7 @@ func TestTest_TestStep_ImportBlockId_ImportStateVerifyIgnore(t *testing.T) {
377377
{
378378
ResourceName: "examplecloud_container.test",
379379
ImportState: true,
380-
ImportStateKind: r.ImportBlockWithId,
380+
ImportStateKind: r.ImportBlockWithID,
381381
ImportStateVerify: true,
382382
ImportStateVerifyIgnore: []string{"password"},
383383
},

helper/resource/importstate/import_command_as_first_step_test.go

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,9 @@ func Test_ImportCommand_AsFirstStep(t *testing.T) {
3333
},
3434
Steps: []r.TestStep{
3535
{
36-
ResourceName: "examplecloud_container.test",
37-
ImportStateId: "examplecloud_container.test",
38-
ImportState: true,
39-
ImportStateKind: r.ImportCommandWithId,
40-
// ImportStateVerify: true,
36+
ResourceName: "examplecloud_container.test",
37+
ImportStateId: "examplecloud_container.test",
38+
ImportState: true,
4139
Config: `resource "examplecloud_container" "test" {
4240
name = "somevalue"
4341
location = "westeurope"
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# Copyright (c) HashiCorp, Inc.
2+
# SPDX-License-Identifier: MPL-2.0
3+
4+
resource "examplecloud_container" "test" {
5+
name = "somevalue"
6+
location = "westeurope"
7+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# Copyright (c) HashiCorp, Inc.
2+
# SPDX-License-Identifier: MPL-2.0
3+
4+
resource "examplecloud_container" "test" {
5+
name = "somevalue"
6+
location = "westeurope"
7+
}
8+
9+
import {
10+
to = examplecloud_container.test
11+
id = "examplecloud_container.test"
12+
}

helper/resource/testing.go

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -457,14 +457,28 @@ type ExternalProvider struct {
457457
type ImportStateKind byte
458458

459459
const (
460-
// ImportCommandWithId imports the state using the import command
461-
ImportCommandWithId ImportStateKind = iota
462-
// ImportBlockWithId imports the state using an import block with an ID
463-
ImportBlockWithId
460+
// ImportCommandWithID tests import by using the ID string with the `terraform import` command
461+
ImportCommandWithID ImportStateKind = iota
462+
463+
// ImportBlockWithID tests import by using the ID string in an import configuration block with the `terraform plan` command
464+
ImportBlockWithID
465+
464466
// ImportBlockWithResourceIdentity imports the state using an import block with a resource identity
465467
ImportBlockWithResourceIdentity
466468
)
467469

470+
func (kind ImportStateKind) plannable() bool {
471+
return kind == ImportBlockWithID || kind == ImportBlockWithResourceIdentity
472+
}
473+
474+
func (kind ImportStateKind) String() string {
475+
return map[ImportStateKind]string{
476+
ImportCommandWithID: "ImportCommandWithID",
477+
ImportBlockWithID: "ImportBlockWithID",
478+
ImportBlockWithResourceIdentity: "ImportBlockWithResourceIdentity",
479+
}[kind]
480+
}
481+
468482
// TestStep is a single apply sequence of a test, done within the
469483
// context of a state.
470484
//
@@ -963,17 +977,17 @@ func UnitTest(t testing.T, c TestCase) {
963977
Test(t, c)
964978
}
965979

966-
func testResource(c TestStep, state *terraform.State) (*terraform.ResourceState, error) {
980+
func testResource(name string, state *terraform.State) (*terraform.ResourceState, error) {
967981
for _, m := range state.Modules {
968982
if len(m.Resources) > 0 {
969-
if v, ok := m.Resources[c.ResourceName]; ok {
983+
if v, ok := m.Resources[name]; ok {
970984
return v, nil
971985
}
972986
}
973987
}
974988

975989
return nil, fmt.Errorf(
976-
"Resource specified by ResourceName couldn't be found: %s", c.ResourceName)
990+
"Resource specified by ResourceName couldn't be found: %s", name)
977991
}
978992

979993
// ComposeTestCheckFunc lets you compose multiple TestCheckFuncs into

0 commit comments

Comments
 (0)