github.com/jrasell/terraform@v0.6.17-0.20160523115548-2652f5232949/helper/resource/testing_config.go (about)

     1  package resource
     2  
     3  import (
     4  	"fmt"
     5  	"log"
     6  
     7  	"github.com/hashicorp/terraform/terraform"
     8  )
     9  
    10  // testStepConfig runs a config-mode test step
    11  func testStepConfig(
    12  	opts terraform.ContextOpts,
    13  	state *terraform.State,
    14  	step TestStep) (*terraform.State, error) {
    15  	return testStep(opts, state, step)
    16  }
    17  
    18  func testStep(
    19  	opts terraform.ContextOpts,
    20  	state *terraform.State,
    21  	step TestStep) (*terraform.State, error) {
    22  	mod, err := testModule(opts, step)
    23  	if err != nil {
    24  		return state, err
    25  	}
    26  
    27  	// Build the context
    28  	opts.Module = mod
    29  	opts.State = state
    30  	opts.Destroy = step.Destroy
    31  	ctx, err := terraform.NewContext(&opts)
    32  	if err != nil {
    33  		return state, fmt.Errorf("Error initializing context: %s", err)
    34  	}
    35  	if ws, es := ctx.Validate(); len(ws) > 0 || len(es) > 0 {
    36  		if len(es) > 0 {
    37  			estrs := make([]string, len(es))
    38  			for i, e := range es {
    39  				estrs[i] = e.Error()
    40  			}
    41  			return state, fmt.Errorf(
    42  				"Configuration is invalid.\n\nWarnings: %#v\n\nErrors: %#v",
    43  				ws, estrs)
    44  		}
    45  		log.Printf("[WARN] Config warnings: %#v", ws)
    46  	}
    47  
    48  	// Refresh!
    49  	state, err = ctx.Refresh()
    50  	if err != nil {
    51  		return state, fmt.Errorf(
    52  			"Error refreshing: %s", err)
    53  	}
    54  
    55  	// Plan!
    56  	if p, err := ctx.Plan(); err != nil {
    57  		return state, fmt.Errorf(
    58  			"Error planning: %s", err)
    59  	} else {
    60  		log.Printf("[WARN] Test: Step plan: %s", p)
    61  	}
    62  
    63  	// We need to keep a copy of the state prior to destroying
    64  	// such that destroy steps can verify their behaviour in the check
    65  	// function
    66  	stateBeforeApplication := state.DeepCopy()
    67  
    68  	// Apply!
    69  	state, err = ctx.Apply()
    70  	if err != nil {
    71  		return state, fmt.Errorf("Error applying: %s", err)
    72  	}
    73  
    74  	// Check! Excitement!
    75  	if step.Check != nil {
    76  		if step.Destroy {
    77  			if err := step.Check(stateBeforeApplication); err != nil {
    78  				return state, fmt.Errorf("Check failed: %s", err)
    79  			}
    80  		} else {
    81  			if err := step.Check(state); err != nil {
    82  				return state, fmt.Errorf("Check failed: %s", err)
    83  			}
    84  		}
    85  	}
    86  
    87  	// Now, verify that Plan is now empty and we don't have a perpetual diff issue
    88  	// We do this with TWO plans. One without a refresh.
    89  	var p *terraform.Plan
    90  	if p, err = ctx.Plan(); err != nil {
    91  		return state, fmt.Errorf("Error on follow-up plan: %s", err)
    92  	}
    93  	if p.Diff != nil && !p.Diff.Empty() {
    94  		if step.ExpectNonEmptyPlan {
    95  			log.Printf("[INFO] Got non-empty plan, as expected:\n\n%s", p)
    96  		} else {
    97  			return state, fmt.Errorf(
    98  				"After applying this step, the plan was not empty:\n\n%s", p)
    99  		}
   100  	}
   101  
   102  	// And another after a Refresh.
   103  	state, err = ctx.Refresh()
   104  	if err != nil {
   105  		return state, fmt.Errorf(
   106  			"Error on follow-up refresh: %s", err)
   107  	}
   108  	if p, err = ctx.Plan(); err != nil {
   109  		return state, fmt.Errorf("Error on second follow-up plan: %s", err)
   110  	}
   111  	if p.Diff != nil && !p.Diff.Empty() {
   112  		if step.ExpectNonEmptyPlan {
   113  			log.Printf("[INFO] Got non-empty plan, as expected:\n\n%s", p)
   114  		} else {
   115  			return state, fmt.Errorf(
   116  				"After applying this step and refreshing, "+
   117  					"the plan was not empty:\n\n%s", p)
   118  		}
   119  	}
   120  
   121  	// Made it here, but expected a non-empty plan, fail!
   122  	if step.ExpectNonEmptyPlan && (p.Diff == nil || p.Diff.Empty()) {
   123  		return state, fmt.Errorf("Expected a non-empty plan, but got an empty plan!")
   124  	}
   125  
   126  	// Made it here? Good job test step!
   127  	return state, nil
   128  }