diff options
Diffstat (limited to 'vendor/github.com/hashicorp/terraform/helper/resource/testing.go')
-rw-r--r-- | vendor/github.com/hashicorp/terraform/helper/resource/testing.go | 148 |
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 @@ | |||
1 | package resource | 1 | package resource |
2 | 2 | ||
3 | import ( | 3 | import ( |
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 | |||
44 | var flagSweep = flag.String("sweep", "", "List of Regions to run available Sweepers") | ||
45 | var flagSweepRun = flag.String("sweep-run", "", "Comma seperated list of Sweeper Tests to run") | ||
46 | var sweeperFuncs map[string]*Sweeper | ||
47 | |||
48 | // map of sweepers that have ran, and the success/fail status based on any error | ||
49 | // raised | ||
50 | var 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. | ||
55 | type SweeperFunc func(r string) error | ||
56 | |||
57 | type 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 | |||
71 | func 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. | ||
80 | func 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 | |||
88 | func 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. | ||
121 | func 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. | ||
144 | func 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 | |||
23 | const TestEnvVar = "TF_ACC" | 171 | const 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 |