github.com/nevins-b/terraform@v0.3.8-0.20170215184714-bbae22007d5a/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  }