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