github.com/graywolf-at-work-2/terraform-vendor@v1.4.5/internal/cloud/e2e/helper_test.go (about) 1 package main 2 3 import ( 4 "context" 5 "fmt" 6 "os" 7 "testing" 8 "time" 9 10 expect "github.com/Netflix/go-expect" 11 tfe "github.com/hashicorp/go-tfe" 12 "github.com/hashicorp/go-uuid" 13 goversion "github.com/hashicorp/go-version" 14 tfversion "github.com/hashicorp/terraform/version" 15 ) 16 17 const ( 18 // We need to give the console enough time to hear back. 19 // 1 minute was too short in some cases, so this gives it ample time. 20 expectConsoleTimeout = 3 * time.Minute 21 ) 22 23 type tfCommand struct { 24 command []string 25 expectedCmdOutput string 26 expectError bool 27 userInput []string 28 postInputOutput []string 29 } 30 31 type operationSets struct { 32 commands []tfCommand 33 prep func(t *testing.T, orgName, dir string) 34 } 35 36 type testCases map[string]struct { 37 operations []operationSets 38 validations func(t *testing.T, orgName string) 39 } 40 41 func defaultOpts() []expect.ConsoleOpt { 42 opts := []expect.ConsoleOpt{ 43 expect.WithDefaultTimeout(expectConsoleTimeout), 44 } 45 if verboseMode { 46 opts = append(opts, expect.WithStdout(os.Stdout)) 47 } 48 return opts 49 } 50 51 func createOrganization(t *testing.T) (*tfe.Organization, func()) { 52 ctx := context.Background() 53 org, err := tfeClient.Organizations.Create(ctx, tfe.OrganizationCreateOptions{ 54 Name: tfe.String("tst-" + randomString(t)), 55 Email: tfe.String(fmt.Sprintf("%s@tfe.local", randomString(t))), 56 CostEstimationEnabled: tfe.Bool(false), 57 }) 58 if err != nil { 59 t.Fatal(err) 60 } 61 62 _, err = tfeClient.Admin.Organizations.Update(ctx, org.Name, tfe.AdminOrganizationUpdateOptions{ 63 AccessBetaTools: tfe.Bool(true), 64 }) 65 if err != nil { 66 t.Fatal(err) 67 } 68 69 return org, func() { 70 if err := tfeClient.Organizations.Delete(ctx, org.Name); err != nil { 71 t.Errorf("Error destroying organization! WARNING: Dangling resources\n"+ 72 "may exist! The full error is shown below.\n\n"+ 73 "Organization: %s\nError: %s", org.Name, err) 74 } 75 } 76 } 77 78 func createWorkspace(t *testing.T, orgName string, wOpts tfe.WorkspaceCreateOptions) *tfe.Workspace { 79 ctx := context.Background() 80 w, err := tfeClient.Workspaces.Create(ctx, orgName, wOpts) 81 if err != nil { 82 t.Fatal(err) 83 } 84 85 return w 86 } 87 88 func getWorkspace(workspaces []*tfe.Workspace, workspace string) (*tfe.Workspace, bool) { 89 for _, ws := range workspaces { 90 if ws.Name == workspace { 91 return ws, false 92 } 93 } 94 return nil, true 95 } 96 97 func randomString(t *testing.T) string { 98 v, err := uuid.GenerateUUID() 99 if err != nil { 100 t.Fatal(err) 101 } 102 return v 103 } 104 105 func terraformConfigLocalBackend() string { 106 return ` 107 terraform { 108 backend "local" { 109 } 110 } 111 112 output "val" { 113 value = "${terraform.workspace}" 114 } 115 ` 116 } 117 118 func terraformConfigRemoteBackendName(org, name string) string { 119 return fmt.Sprintf(` 120 terraform { 121 backend "remote" { 122 hostname = "%s" 123 organization = "%s" 124 125 workspaces { 126 name = "%s" 127 } 128 } 129 } 130 131 output "val" { 132 value = "${terraform.workspace}" 133 } 134 `, tfeHostname, org, name) 135 } 136 137 func terraformConfigRemoteBackendPrefix(org, prefix string) string { 138 return fmt.Sprintf(` 139 terraform { 140 backend "remote" { 141 hostname = "%s" 142 organization = "%s" 143 144 workspaces { 145 prefix = "%s" 146 } 147 } 148 } 149 150 output "val" { 151 value = "${terraform.workspace}" 152 } 153 `, tfeHostname, org, prefix) 154 } 155 156 func terraformConfigCloudBackendTags(org, tag string) string { 157 return fmt.Sprintf(` 158 terraform { 159 cloud { 160 hostname = "%s" 161 organization = "%s" 162 163 workspaces { 164 tags = ["%s"] 165 } 166 } 167 } 168 169 output "tag_val" { 170 value = "%s" 171 } 172 `, tfeHostname, org, tag, tag) 173 } 174 175 func terraformConfigCloudBackendName(org, name string) string { 176 return fmt.Sprintf(` 177 terraform { 178 cloud { 179 hostname = "%s" 180 organization = "%s" 181 182 workspaces { 183 name = "%s" 184 } 185 } 186 } 187 188 output "val" { 189 value = "${terraform.workspace}" 190 } 191 `, tfeHostname, org, name) 192 } 193 194 func terraformConfigCloudBackendOmitOrg(workspaceName string) string { 195 return fmt.Sprintf(` 196 terraform { 197 cloud { 198 hostname = "%s" 199 200 workspaces { 201 name = "%s" 202 } 203 } 204 } 205 206 output "val" { 207 value = "${terraform.workspace}" 208 } 209 `, tfeHostname, workspaceName) 210 } 211 212 func terraformConfigCloudBackendOmitWorkspaces(orgName string) string { 213 return fmt.Sprintf(` 214 terraform { 215 cloud { 216 hostname = "%s" 217 organization = "%s" 218 } 219 } 220 221 output "val" { 222 value = "${terraform.workspace}" 223 } 224 `, tfeHostname, orgName) 225 } 226 227 func terraformConfigCloudBackendOmitConfig() string { 228 return ` 229 terraform { 230 cloud {} 231 } 232 233 output "val" { 234 value = "${terraform.workspace}" 235 } 236 ` 237 } 238 239 func writeMainTF(t *testing.T, block string, dir string) { 240 f, err := os.Create(fmt.Sprintf("%s/main.tf", dir)) 241 if err != nil { 242 t.Fatal(err) 243 } 244 _, err = f.WriteString(block) 245 if err != nil { 246 t.Fatal(err) 247 } 248 f.Close() 249 } 250 251 // The e2e tests rely on the fact that the terraform version in TFC/E is able to 252 // run the `cloud` configuration block, which is available in 1.1 and will 253 // continue to be available in later versions. So this function checks that 254 // there is a version that is >= 1.1. 255 func skipWithoutRemoteTerraformVersion(t *testing.T) { 256 version := tfversion.Version 257 baseVersion, err := goversion.NewVersion(version) 258 if err != nil { 259 t.Fatalf(fmt.Sprintf("Error instantiating go-version for %s", version)) 260 } 261 opts := &tfe.AdminTerraformVersionsListOptions{ 262 ListOptions: tfe.ListOptions{ 263 PageNumber: 1, 264 PageSize: 100, 265 }, 266 } 267 hasVersion := false 268 269 findTfVersion: 270 for { 271 // TODO: update go-tfe Read() to retrieve a terraform version by name. 272 // Currently you can only retrieve by ID. 273 tfVersionList, err := tfeClient.Admin.TerraformVersions.List(context.Background(), opts) 274 if err != nil { 275 t.Fatalf("Could not retrieve list of terraform versions: %v", err) 276 } 277 for _, item := range tfVersionList.Items { 278 availableVersion, err := goversion.NewVersion(item.Version) 279 if err != nil { 280 t.Logf("Error instantiating go-version for %s", item.Version) 281 continue 282 } 283 if availableVersion.Core().GreaterThanOrEqual(baseVersion.Core()) { 284 hasVersion = true 285 break findTfVersion 286 } 287 } 288 289 // Exit the loop when we've seen all pages. 290 if tfVersionList.CurrentPage >= tfVersionList.TotalPages { 291 break 292 } 293 294 // Update the page number to get the next page. 295 opts.PageNumber = tfVersionList.NextPage 296 } 297 298 if !hasVersion { 299 t.Skipf("Skipping test because TFC/E does not have current Terraform version to test with (%s)", version) 300 } 301 }