helper/resource: ImportState test can verify states
This commit is contained in:
parent
27452f0043
commit
6a675b4a15
|
@ -149,6 +149,11 @@ type TestStep struct {
|
|||
// used to verify that the resulting value of ImportState has the
|
||||
// proper resources, IDs, and attributes.
|
||||
ImportStateCheck ImportStateCheckFunc
|
||||
|
||||
// ImportStateVerify, if true, will also check that the state values
|
||||
// that are finally put into the state after import match for all the
|
||||
// IDs returned by the Import.
|
||||
ImportStateVerify bool
|
||||
}
|
||||
|
||||
// Test performs an acceptance test on a resource.
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
package resource
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"reflect"
|
||||
|
||||
"github.com/davecgh/go-spew/spew"
|
||||
"github.com/hashicorp/terraform/terraform"
|
||||
)
|
||||
|
||||
|
@ -36,11 +39,11 @@ func testStepImportState(
|
|||
return state, err
|
||||
}
|
||||
|
||||
// TODO: ImportOpts needs a flag to read a config module so it
|
||||
// can load our provider config without env vars.
|
||||
|
||||
// Do the import!
|
||||
newState, err := ctx.Import(&terraform.ImportOpts{
|
||||
// Set the module so that any provider config is loaded
|
||||
Module: mod,
|
||||
|
||||
Targets: []*terraform.ImportTarget{
|
||||
&terraform.ImportTarget{
|
||||
Addr: step.ResourceName,
|
||||
|
@ -66,6 +69,47 @@ func testStepImportState(
|
|||
}
|
||||
}
|
||||
|
||||
// Verify that all the states match
|
||||
if step.ImportStateVerify {
|
||||
new := newState.RootModule().Resources
|
||||
old := state.RootModule().Resources
|
||||
for _, r := range new {
|
||||
// Find the existing resource
|
||||
var oldR *terraform.ResourceState
|
||||
for _, r2 := range old {
|
||||
if r2.Primary != nil && r2.Primary.ID == r.Primary.ID {
|
||||
oldR = r2
|
||||
break
|
||||
}
|
||||
}
|
||||
if oldR == nil {
|
||||
return state, fmt.Errorf(
|
||||
"Failed state verification, resource with ID %s not found",
|
||||
r.Primary.ID)
|
||||
}
|
||||
|
||||
// Compare their attributes
|
||||
actual := r.Primary.Attributes
|
||||
expected := oldR.Primary.Attributes
|
||||
if !reflect.DeepEqual(actual, expected) {
|
||||
// Determine only the different attributes
|
||||
for k, v := range expected {
|
||||
if av, ok := actual[k]; ok && v == av {
|
||||
delete(expected, k)
|
||||
delete(actual, k)
|
||||
}
|
||||
}
|
||||
|
||||
spewConf := spew.NewDefaultConfig()
|
||||
spewConf.SortKeys = true
|
||||
return state, fmt.Errorf(
|
||||
"Attributes not equivalent. Difference is shown below. Top is actual, bottom is expected."+
|
||||
"\n\n%s\n\n%s",
|
||||
spewConf.Sdump(actual), spewConf.Sdump(expected))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Return the old state (non-imported) so we don't change anything.
|
||||
return state, nil
|
||||
}
|
||||
|
|
|
@ -177,3 +177,134 @@ func TestTest_importStateDetectId(t *testing.T) {
|
|||
t.Fatal("didn't call check")
|
||||
}
|
||||
}
|
||||
|
||||
func TestTest_importStateVerify(t *testing.T) {
|
||||
mp := testProvider()
|
||||
mp.DiffReturn = nil
|
||||
mp.ApplyFn = func(
|
||||
info *terraform.InstanceInfo,
|
||||
state *terraform.InstanceState,
|
||||
diff *terraform.InstanceDiff) (*terraform.InstanceState, error) {
|
||||
if !diff.Destroy {
|
||||
return &terraform.InstanceState{
|
||||
ID: "foo",
|
||||
Attributes: map[string]string{
|
||||
"foo": "bar",
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
mp.RefreshFn = func(
|
||||
i *terraform.InstanceInfo,
|
||||
s *terraform.InstanceState) (*terraform.InstanceState, error) {
|
||||
if len(s.Attributes) == 0 {
|
||||
s.Attributes = map[string]string{
|
||||
"id": s.ID,
|
||||
"foo": "bar",
|
||||
}
|
||||
}
|
||||
|
||||
return s, nil
|
||||
}
|
||||
|
||||
mp.ImportStateFn = func(
|
||||
info *terraform.InstanceInfo, id string) ([]*terraform.InstanceState, error) {
|
||||
if id != "foo" {
|
||||
return nil, fmt.Errorf("bad import ID: %s", id)
|
||||
}
|
||||
|
||||
return []*terraform.InstanceState{
|
||||
&terraform.InstanceState{
|
||||
ID: "foo",
|
||||
Ephemeral: terraform.EphemeralState{Type: "test_instance"},
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
mt := new(mockT)
|
||||
Test(mt, TestCase{
|
||||
Providers: map[string]terraform.ResourceProvider{
|
||||
"test": mp,
|
||||
},
|
||||
|
||||
Steps: []TestStep{
|
||||
TestStep{
|
||||
Config: testConfigStr,
|
||||
},
|
||||
TestStep{
|
||||
ResourceName: "test_instance.foo",
|
||||
ImportState: true,
|
||||
ImportStateVerify: true,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
if mt.failed() {
|
||||
t.Fatalf("test failed: %s", mt.failMessage())
|
||||
}
|
||||
}
|
||||
|
||||
func TestTest_importStateVerifyFail(t *testing.T) {
|
||||
mp := testProvider()
|
||||
mp.DiffReturn = nil
|
||||
mp.ApplyFn = func(
|
||||
info *terraform.InstanceInfo,
|
||||
state *terraform.InstanceState,
|
||||
diff *terraform.InstanceDiff) (*terraform.InstanceState, error) {
|
||||
if !diff.Destroy {
|
||||
return &terraform.InstanceState{
|
||||
ID: "foo",
|
||||
Attributes: map[string]string{
|
||||
"foo": "bar",
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
mp.RefreshFn = func(
|
||||
i *terraform.InstanceInfo,
|
||||
s *terraform.InstanceState) (*terraform.InstanceState, error) {
|
||||
return s, nil
|
||||
}
|
||||
|
||||
mp.ImportStateFn = func(
|
||||
info *terraform.InstanceInfo, id string) ([]*terraform.InstanceState, error) {
|
||||
if id != "foo" {
|
||||
return nil, fmt.Errorf("bad import ID: %s", id)
|
||||
}
|
||||
|
||||
return []*terraform.InstanceState{
|
||||
&terraform.InstanceState{
|
||||
ID: "foo",
|
||||
Ephemeral: terraform.EphemeralState{Type: "test_instance"},
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
mt := new(mockT)
|
||||
Test(mt, TestCase{
|
||||
Providers: map[string]terraform.ResourceProvider{
|
||||
"test": mp,
|
||||
},
|
||||
|
||||
Steps: []TestStep{
|
||||
TestStep{
|
||||
Config: testConfigStr,
|
||||
},
|
||||
TestStep{
|
||||
ResourceName: "test_instance.foo",
|
||||
ImportState: true,
|
||||
ImportStateVerify: true,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
if !mt.failed() {
|
||||
t.Fatalf("test should fail")
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue