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