@@ -4,6 +4,7 @@ package provider
44
55import (
66 "fmt"
7+ "io/ioutil"
78 "log"
89 "os"
910 "os/exec"
@@ -13,8 +14,13 @@ import (
1314)
1415
1516const examplesTestStateFile = "test_examples.tfstate"
17+ const defaultTerraformBinary = "terraform"
18+ const vcnExamplePath = "../docs/examples/networking/vcn"
19+ const localBinPath = "/usr/local/bin"
20+ const tfPluginDir = "~/.terraform.d/plugins"
1621
1722var examplesTestAllowedEnvironmentVariables = []string {
23+ "HOME" ,
1824 "PATH" ,
1925 "TF_VAR_user_ocid" ,
2026 "TF_VAR_tenancy_ocid" ,
@@ -36,6 +42,12 @@ func TestExamplesApply(t *testing.T) {
3642 RunExamples (t , false )
3743}
3844
45+ func TestTerraformVersions (t * testing.T ) {
46+ if RunConfigOnAllTerraformVersions (t , vcnExamplePath , false ) {
47+ log .Printf ("Successfully ran all Terraform version tests" )
48+ }
49+ }
50+
3951func RunExamples (t * testing.T , planOnly bool ) {
4052 rootPath := "../docs/examples"
4153 log .Printf ("Testing examples under %v" , rootPath )
@@ -47,12 +59,30 @@ func RunExamples(t *testing.T, planOnly bool) {
4759 }
4860
4961 for _ , dir := range pathList {
50- if RunConfig (t , dir , planOnly ) {
62+ if RunConfig (t , dir , planOnly , defaultTerraformBinary ) {
5163 log .Printf ("Success" )
5264 }
5365 }
5466}
5567
68+ func GetTerraformBinaries (binPath string ) ([]string , error ) {
69+ results := []string {}
70+
71+ entries , err := ioutil .ReadDir (binPath )
72+ if err != nil {
73+ return results , err
74+ }
75+
76+ for _ , entry := range entries {
77+ // Include any binaries that start with "terraform" prefix
78+ if name := entry .Name (); ! entry .IsDir () && strings .HasPrefix (name , defaultTerraformBinary ) {
79+ results = append (results , name )
80+ }
81+ }
82+
83+ return results , nil
84+ }
85+
5686func GetConfigPaths (t * testing.T , rootPath string ) (pathList []string , err error ) {
5787 dirSet := make (map [string ]struct {})
5888
@@ -81,25 +111,60 @@ func GetConfigPaths(t *testing.T, rootPath string) (pathList []string, err error
81111 return pathList , err
82112}
83113
84- func RunConfig (t * testing.T , path string , planOnly bool ) bool {
114+ func RunConfigOnAllTerraformVersions (t * testing.T , path string , planOnly bool ) bool {
115+ terraformBinaries , err := GetTerraformBinaries (localBinPath )
116+ if err != nil {
117+ t .Errorf ("Error retrieving terraform binaries: %v" , err )
118+ return false
119+ }
120+
121+ if len (terraformBinaries ) == 0 {
122+ t .Errorf ("Did not find any terraform binaries" )
123+ return false
124+ }
125+
126+ result := true
127+ for _ , tfBin := range terraformBinaries {
128+ log .Printf ("=== Terraform Version ('%s'), Config Path ('%s') ===\n " , tfBin , path )
129+ if ! runCommandWithOutputOptions (t , path , fmt .Sprintf ("%s version" , tfBin ), true ) {
130+ log .Printf ("Unable to run version command. Skipping test for %s.\n " , tfBin )
131+ result = false
132+ continue
133+ }
134+
135+ if ! RunConfig (t , path , planOnly , tfBin ) {
136+ log .Printf ("Failed to run test on version '%s'\n " , tfBin )
137+ result = false
138+ }
139+ }
140+
141+ return result
142+ }
143+
144+ func RunConfig (t * testing.T , path string , planOnly bool , terraformBinary string ) bool {
85145 // Fail if a state file already exists, since that indicates that a previous run did not
86146 // properly clean up.
87147 if _ , err := os .Stat (filepath .Join (path , examplesTestStateFile )); err == nil {
88148 t .Errorf ("State file '%v' already exists at %v." , examplesTestStateFile , path )
89149 return false
90150 }
91151
92- if ! RunCommand (t , path , "terraform init" ) {
152+ terraformCommand := terraformBinary
153+ if terraformCommand == "" {
154+ terraformCommand = defaultTerraformBinary
155+ }
156+
157+ if ! RunCommand (t , path , fmt .Sprintf ("%s init -plugin-dir %s" , terraformCommand , tfPluginDir )) {
93158 return false
94159 }
95160
96161 if planOnly {
97- return RunCommand (t , path , fmt .Sprintf ("terraform plan -state=%v" , examplesTestStateFile ))
162+ return RunCommand (t , path , fmt .Sprintf ("%s plan -state=%v" , terraformCommand , examplesTestStateFile ))
98163 } else {
99- result := RunCommand (t , path , fmt .Sprintf ("terraform apply -auto-approve -state=%v" , examplesTestStateFile ))
164+ result := RunCommand (t , path , fmt .Sprintf ("%s apply -auto-approve -state=%v" , terraformCommand , examplesTestStateFile ))
100165
101166 // Regardless of the result, attempt to destroy.
102- if RunCommand (t , path , fmt .Sprintf ("terraform destroy -force -state=%v" , examplesTestStateFile )) {
167+ if RunCommand (t , path , fmt .Sprintf ("%s destroy -force -state=%v" , terraformCommand , examplesTestStateFile )) {
103168 // Only remove the state file if destroy was successful. Otherwise, leave it in place so that further
104169 // cleanup can be done manually.
105170 result = RunCommand (t , path , fmt .Sprintf ("rm %v*" , examplesTestStateFile )) && result
@@ -112,6 +177,10 @@ func RunConfig(t *testing.T, path string, planOnly bool) bool {
112177}
113178
114179func RunCommand (t * testing.T , path , command string ) bool {
180+ return runCommandWithOutputOptions (t , path , command , false )
181+ }
182+
183+ func runCommandWithOutputOptions (t * testing.T , path , command string , displayOutputOnSuccess bool ) bool {
115184 log .Printf ("Running command '%v' at %v" , command , path )
116185
117186 env := make ([]string , len (examplesTestAllowedEnvironmentVariables ))
@@ -130,5 +199,9 @@ func RunCommand(t *testing.T, path, command string) bool {
130199 return false
131200 }
132201
202+ if displayOutputOnSuccess {
203+ log .Printf ("Output: %s" , output )
204+ }
205+
133206 return true
134207}
0 commit comments