aboutsummaryrefslogtreecommitdiffhomepage
path: root/vendor/github.com/hashicorp/terraform/helper/resource/testing.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/hashicorp/terraform/helper/resource/testing.go')
-rw-r--r--vendor/github.com/hashicorp/terraform/helper/resource/testing.go148
1 files changed, 148 insertions, 0 deletions
diff --git a/vendor/github.com/hashicorp/terraform/helper/resource/testing.go b/vendor/github.com/hashicorp/terraform/helper/resource/testing.go
index 04367c5..ebdbde2 100644
--- a/vendor/github.com/hashicorp/terraform/helper/resource/testing.go
+++ b/vendor/github.com/hashicorp/terraform/helper/resource/testing.go
@@ -1,6 +1,7 @@
1package resource 1package resource
2 2
3import ( 3import (
4 "flag"
4 "fmt" 5 "fmt"
5 "io" 6 "io"
6 "io/ioutil" 7 "io/ioutil"
@@ -20,6 +21,153 @@ import (
20 "github.com/hashicorp/terraform/terraform" 21 "github.com/hashicorp/terraform/terraform"
21) 22)
22 23
24// flagSweep is a flag available when running tests on the command line. It
25// contains a comma seperated list of regions to for the sweeper functions to
26// run in. This flag bypasses the normal Test path and instead runs functions designed to
27// clean up any leaked resources a testing environment could have created. It is
28// a best effort attempt, and relies on Provider authors to implement "Sweeper"
29// methods for resources.
30
31// Adding Sweeper methods with AddTestSweepers will
32// construct a list of sweeper funcs to be called here. We iterate through
33// regions provided by the sweep flag, and for each region we iterate through the
34// tests, and exit on any errors. At time of writing, sweepers are ran
35// sequentially, however they can list dependencies to be ran first. We track
36// the sweepers that have been ran, so as to not run a sweeper twice for a given
37// region.
38//
39// WARNING:
40// Sweepers are designed to be destructive. You should not use the -sweep flag
41// in any environment that is not strictly a test environment. Resources will be
42// destroyed.
43
44var flagSweep = flag.String("sweep", "", "List of Regions to run available Sweepers")
45var flagSweepRun = flag.String("sweep-run", "", "Comma seperated list of Sweeper Tests to run")
46var sweeperFuncs map[string]*Sweeper
47
48// map of sweepers that have ran, and the success/fail status based on any error
49// raised
50var sweeperRunList map[string]bool
51
52// type SweeperFunc is a signature for a function that acts as a sweeper. It
53// accepts a string for the region that the sweeper is to be ran in. This
54// function must be able to construct a valid client for that region.
55type SweeperFunc func(r string) error
56
57type Sweeper struct {
58 // Name for sweeper. Must be unique to be ran by the Sweeper Runner
59 Name string
60
61 // Dependencies list the const names of other Sweeper functions that must be ran
62 // prior to running this Sweeper. This is an ordered list that will be invoked
63 // recursively at the helper/resource level
64 Dependencies []string
65
66 // Sweeper function that when invoked sweeps the Provider of specific
67 // resources
68 F SweeperFunc
69}
70
71func init() {
72 sweeperFuncs = make(map[string]*Sweeper)
73}
74
75// AddTestSweepers function adds a given name and Sweeper configuration
76// pair to the internal sweeperFuncs map. Invoke this function to register a
77// resource sweeper to be available for running when the -sweep flag is used
78// with `go test`. Sweeper names must be unique to help ensure a given sweeper
79// is only ran once per run.
80func AddTestSweepers(name string, s *Sweeper) {
81 if _, ok := sweeperFuncs[name]; ok {
82 log.Fatalf("[ERR] Error adding (%s) to sweeperFuncs: function already exists in map", name)
83 }
84
85 sweeperFuncs[name] = s
86}
87
88func TestMain(m *testing.M) {
89 flag.Parse()
90 if *flagSweep != "" {
91 // parse flagSweep contents for regions to run
92 regions := strings.Split(*flagSweep, ",")
93
94 // get filtered list of sweepers to run based on sweep-run flag
95 sweepers := filterSweepers(*flagSweepRun, sweeperFuncs)
96 for _, region := range regions {
97 region = strings.TrimSpace(region)
98 // reset sweeperRunList for each region
99 sweeperRunList = map[string]bool{}
100
101 log.Printf("[DEBUG] Running Sweepers for region (%s):\n", region)
102 for _, sweeper := range sweepers {
103 if err := runSweeperWithRegion(region, sweeper); err != nil {
104 log.Fatalf("[ERR] error running (%s): %s", sweeper.Name, err)
105 }
106 }
107
108 log.Printf("Sweeper Tests ran:\n")
109 for s, _ := range sweeperRunList {
110 fmt.Printf("\t- %s\n", s)
111 }
112 }
113 } else {
114 os.Exit(m.Run())
115 }
116}
117
118// filterSweepers takes a comma seperated string listing the names of sweepers
119// to be ran, and returns a filtered set from the list of all of sweepers to
120// run based on the names given.
121func filterSweepers(f string, source map[string]*Sweeper) map[string]*Sweeper {
122 filterSlice := strings.Split(strings.ToLower(f), ",")
123 if len(filterSlice) == 1 && filterSlice[0] == "" {
124 // if the filter slice is a single element of "" then no sweeper list was
125 // given, so just return the full list
126 return source
127 }
128
129 sweepers := make(map[string]*Sweeper)
130 for name, sweeper := range source {
131 for _, s := range filterSlice {
132 if strings.Contains(strings.ToLower(name), s) {
133 sweepers[name] = sweeper
134 }
135 }
136 }
137 return sweepers
138}
139
140// runSweeperWithRegion recieves a sweeper and a region, and recursively calls
141// itself with that region for every dependency found for that sweeper. If there
142// are no dependencies, invoke the contained sweeper fun with the region, and
143// add the success/fail status to the sweeperRunList.
144func runSweeperWithRegion(region string, s *Sweeper) error {
145 for _, dep := range s.Dependencies {
146 if depSweeper, ok := sweeperFuncs[dep]; ok {
147 log.Printf("[DEBUG] Sweeper (%s) has dependency (%s), running..", s.Name, dep)
148 if err := runSweeperWithRegion(region, depSweeper); err != nil {
149 return err
150 }
151 } else {
152 log.Printf("[DEBUG] Sweeper (%s) has dependency (%s), but that sweeper was not found", s.Name, dep)
153 }
154 }
155
156 if _, ok := sweeperRunList[s.Name]; ok {
157 log.Printf("[DEBUG] Sweeper (%s) already ran in region (%s)", s.Name, region)
158 return nil
159 }
160
161 runE := s.F(region)
162 if runE == nil {
163 sweeperRunList[s.Name] = true
164 } else {
165 sweeperRunList[s.Name] = false
166 }
167
168 return runE
169}
170
23const TestEnvVar = "TF_ACC" 171const TestEnvVar = "TF_ACC"
24 172
25// TestProvider can be implemented by any ResourceProvider to provide custom 173// TestProvider can be implemented by any ResourceProvider to provide custom