github.com/richardmarshall/terraform@v0.9.5-0.20170429023105-15704cc6ee35/helper/resource/testing_import_state.go (about) 1 package resource 2 3 import ( 4 "fmt" 5 "log" 6 "reflect" 7 "strings" 8 9 "github.com/davecgh/go-spew/spew" 10 "github.com/hashicorp/terraform/terraform" 11 ) 12 13 // testStepImportState runs an imort state test step 14 func testStepImportState( 15 opts terraform.ContextOpts, 16 state *terraform.State, 17 step TestStep) (*terraform.State, error) { 18 // Determine the ID to import 19 importId := step.ImportStateId 20 if importId == "" { 21 resource, err := testResource(step, state) 22 if err != nil { 23 return state, err 24 } 25 26 importId = resource.Primary.ID 27 } 28 importPrefix := step.ImportStateIdPrefix 29 if importPrefix != "" { 30 importId = fmt.Sprintf("%s%s", importPrefix, importId) 31 } 32 33 // Setup the context. We initialize with an empty state. We use the 34 // full config for provider configurations. 35 mod, err := testModule(opts, step) 36 if err != nil { 37 return state, err 38 } 39 40 opts.Module = mod 41 opts.State = terraform.NewState() 42 ctx, err := terraform.NewContext(&opts) 43 if err != nil { 44 return state, err 45 } 46 47 // Do the import! 48 newState, err := ctx.Import(&terraform.ImportOpts{ 49 // Set the module so that any provider config is loaded 50 Module: mod, 51 52 Targets: []*terraform.ImportTarget{ 53 &terraform.ImportTarget{ 54 Addr: step.ResourceName, 55 ID: importId, 56 }, 57 }, 58 }) 59 if err != nil { 60 log.Printf("[ERROR] Test: ImportState failure: %s", err) 61 return state, err 62 } 63 64 // Go through the new state and verify 65 if step.ImportStateCheck != nil { 66 var states []*terraform.InstanceState 67 for _, r := range newState.RootModule().Resources { 68 if r.Primary != nil { 69 states = append(states, r.Primary) 70 } 71 } 72 if err := step.ImportStateCheck(states); err != nil { 73 return state, err 74 } 75 } 76 77 // Verify that all the states match 78 if step.ImportStateVerify { 79 new := newState.RootModule().Resources 80 old := state.RootModule().Resources 81 for _, r := range new { 82 // Find the existing resource 83 var oldR *terraform.ResourceState 84 for _, r2 := range old { 85 if r2.Primary != nil && r2.Primary.ID == r.Primary.ID && r2.Type == r.Type { 86 oldR = r2 87 break 88 } 89 } 90 if oldR == nil { 91 return state, fmt.Errorf( 92 "Failed state verification, resource with ID %s not found", 93 r.Primary.ID) 94 } 95 96 // Compare their attributes 97 actual := make(map[string]string) 98 for k, v := range r.Primary.Attributes { 99 actual[k] = v 100 } 101 expected := make(map[string]string) 102 for k, v := range oldR.Primary.Attributes { 103 expected[k] = v 104 } 105 106 // Remove fields we're ignoring 107 for _, v := range step.ImportStateVerifyIgnore { 108 for k, _ := range actual { 109 if strings.HasPrefix(k, v) { 110 delete(actual, k) 111 } 112 } 113 for k, _ := range expected { 114 if strings.HasPrefix(k, v) { 115 delete(expected, k) 116 } 117 } 118 } 119 120 if !reflect.DeepEqual(actual, expected) { 121 // Determine only the different attributes 122 for k, v := range expected { 123 if av, ok := actual[k]; ok && v == av { 124 delete(expected, k) 125 delete(actual, k) 126 } 127 } 128 129 spewConf := spew.NewDefaultConfig() 130 spewConf.SortKeys = true 131 return state, fmt.Errorf( 132 "ImportStateVerify attributes not equivalent. Difference is shown below. Top is actual, bottom is expected."+ 133 "\n\n%s\n\n%s", 134 spewConf.Sdump(actual), spewConf.Sdump(expected)) 135 } 136 } 137 } 138 139 // Return the old state (non-imported) so we don't change anything. 140 return state, nil 141 }