github.com/miquella/terraform@v0.6.17-0.20160517195040-40db82f25ec0/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 }