Skip to content

Commit

Permalink
Merge pull request #188 from hashicorp/e2e-refactor-utils
Browse files Browse the repository at this point in the history
Refactor enterprise e2e test utilities
  • Loading branch information
mkam committed Oct 28, 2021
2 parents e055613 + 4763ab4 commit 4431fe6
Show file tree
Hide file tree
Showing 5 changed files with 177 additions and 142 deletions.
2 changes: 1 addition & 1 deletion driver/tfc_test.go
Expand Up @@ -204,7 +204,7 @@ func TestTerraformCloud_UpdateTask_Inspect(t *testing.T) {
ctx := context.Background()
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
workingDir := strings.ReplaceAll(tc.name, " ", "_")
workingDir := "tfc_" + strings.ReplaceAll(tc.name, " ", "_")
deleteTemp := testutils.MakeTempDir(t, workingDir)
defer deleteTemp()

Expand Down
9 changes: 6 additions & 3 deletions e2e/command_tfc_test.go
@@ -1,5 +1,5 @@
// +build e2e
// +build enterprise
//go:build e2e && enterprise
// +build e2e,enterprise

// Tests CTS CLI commands interacting with a running CTS in daemon mode.
package e2e
Expand Down Expand Up @@ -51,9 +51,12 @@ func TestE2E_TFC_EnableTaskCommand(t *testing.T) {

for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
srv := newTestConsulServer(t)
defer srv.Stop()

wsName := testutils.RandomWorkspaceName(t)
tempDir := fmt.Sprintf("%s%s", tempDirPrefix, "enable_cmd")
cts, _ := ctsTFCSetup(t, tfcConfig, wsName, disabledTaskConfig(tempDir), tempDir)
cts := ctsTFCSetup(t, srv, tfcConfig, wsName, disabledTaskConfig(tempDir), tempDir)

subcmd := []string{"task", "enable", fmt.Sprintf("-port=%d", cts.Port())}
subcmd = append(subcmd, tc.args...)
Expand Down
45 changes: 45 additions & 0 deletions e2e/config_ent.go
@@ -0,0 +1,45 @@
//go:build e2e && enterprise
// +build e2e,enterprise

package e2e

import (
"fmt"
"strings"
)

func (c hclConfig) appendTerraformCloudBlock(hostname string, org string, token string, opts ...string) hclConfig {
var optsConfig string
if len(opts) > 0 {
optsConfig = "\n" + strings.Join(opts, "\n")
}

return c.appendString(fmt.Sprintf(`
driver "terraform-cloud" {
hostname = "%s"
organization = "%s"
token = "%s"
%s
}`, hostname, org, token, optsConfig))
}

func (c hclConfig) appendModuleTask(name string, source string, opts ...string) hclConfig {
return c.appendString(moduleTaskConfig(name, source, opts...))
}

func moduleTaskConfig(name string, source string, opts ...string) string {
var optsConfig string
if len(opts) > 0 {
optsConfig = "\n" + strings.Join(opts, "\n")
}

return fmt.Sprintf(`
task {
name = "%s"
description = "e2e test"
services = ["api", "web"]
source = "%s"
%s
}
`, name, source, optsConfig)
}
157 changes: 19 additions & 138 deletions e2e/e2e_tfc_test.go
@@ -1,5 +1,5 @@
// +build e2e
// +build enterprise
//go:build e2e && enterprise
// +build e2e,enterprise

package e2e

Expand All @@ -12,7 +12,6 @@ import (
"os/exec"
"path/filepath"
"strconv"
"strings"
"testing"
"time"

Expand All @@ -27,20 +26,6 @@ import (
"github.com/stretchr/testify/require"
)

const (
// liberal default times to wait
defaultWaitForEntAPI = 180 * time.Second

tfVersion = `terraform_version = "1.0.8"`
// remote and local version of the same module
remote = "mkam/hello/cts"
local = "./test_modules/hello"

privKeyPath = "../licensing/consul-dev-licenser.priv"
)

var tfcConfig *testutils.TerraformCloudTestConfig

func TestMain(m *testing.M) {
run := func() int {
cleanup, err := devlicensing.MakeDevLicenseFile(devlicensing.DefaultTestLicensePath, privKeyPath, 30*time.Minute)
Expand All @@ -61,53 +46,6 @@ func TestMain(m *testing.M) {
os.Exit(run())
}

// ctsTFCSetup executes common setup steps for end-to-end testing of the terraform-cloud driver.
// It creates a CTS config file based on the given TFC config, workspace name, and task configuration.
// The steps executed are:
// 1. Starts Consul
// 2. Creates a temporary working directory
// 3. Creates a CTS configuration file
// 4. Starts CTS
// 5. Waits for the CTS API to start without error, indicating that all initialization is complete
func ctsTFCSetup(t *testing.T, tfcConfig *testutils.TerraformCloudTestConfig,
wsName, taskConfig, tempDir string) (*api.Client, *testutil.TestServer) {
// Start Consul Server
srv := newTestConsulServer(t)
t.Cleanup(func() {
srv.Stop()
})

// Create temporary working directory
deleteDir := testutils.MakeTempDir(t, tempDir)
t.Cleanup(func() {
deleteDir()
})

// Create configuration based on given TFC configs and module
configPath := filepath.Join(tempDir, configFile)
config := baseConfig(tempDir).appendConsulBlock(srv).
appendTerraformCloudBlock(tfcConfig.Hostname, tfcConfig.Org, tfcConfig.Token).
appendString(taskConfig)
config.write(t, configPath)

// Add cleanup for workspace
t.Cleanup(func() {
ctx := context.Background()
client := testutils.NewTerraformCloudTestClient(t, tfcConfig)
client.Workspaces.Delete(ctx, tfcConfig.Org, wsName)
})

// Start CTS and wait for once mode to complete before verifying
cts, stop := api.StartCTS(t, configPath)
t.Cleanup(func() {
stop(t)
})
err := cts.WaitForAPI(defaultWaitForEntAPI)
require.NoError(t, err)

return cts, srv
}

// TestE2EEnterprise runs the CTS binary in daemon mode with a single task configured
// and a test module that creates a file that references all Consul services. It verifies
// via the TerraformCloud API that:
Expand Down Expand Up @@ -135,10 +73,12 @@ func TestE2EEnterprise(t *testing.T) {
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
// Set up Consul and CTS
srv := newTestConsulServer(t)
defer srv.Stop()
wsName := testutils.RandomWorkspaceName(t)
tempDir := fmt.Sprintf("%s%s_%s", tempDirPrefix, "enterprise", tc.name)
taskConfig := moduleTaskConfig(wsName, tc.source)
cts, srv := ctsTFCSetup(t, tfcConfig, wsName, taskConfig, tempDir)
cts := ctsTFCSetup(t, srv, tfcConfig, wsName, taskConfig, tempDir)

// Verify workspace was created
ctx := context.Background()
Expand Down Expand Up @@ -204,11 +144,13 @@ func TestE2EEnterprise(t *testing.T) {
func TestE2EEnterprise_SelfHosted(t *testing.T) {
t.Parallel()
// Setup Consul and CTS
srv := newTestConsulServer(t)
defer srv.Stop()
tfeConfig, err := testutils.NewTerraformCloudTestConfig(testutils.TFE)
require.NoError(t, err)
tempDir := fmt.Sprintf("%s%s", tempDirPrefix, "enterprise_tfe")
wsName := testutils.RandomWorkspaceName(t)
ctsTFCSetup(t, tfeConfig, wsName, moduleTaskConfig(wsName, remote), tempDir)
ctsTFCSetup(t, srv, tfeConfig, wsName, moduleTaskConfig(wsName, remote), tempDir)

// Verify workspace was created
ctx := context.Background()
Expand Down Expand Up @@ -269,11 +211,14 @@ func TestE2EEnterprise_Restart(t *testing.T) {
func TestE2EEnterprise_TaskCLI(t *testing.T) {
t.Parallel()

srv := newTestConsulServer(t)
defer srv.Stop()

tempDir := fmt.Sprintf("%s%s", tempDirPrefix, "ent_disable_enable")
wsName := testutils.RandomWorkspaceName(t)

taskConfig := moduleTaskConfig(wsName, remote)
cts, _ := ctsTFCSetup(t, tfcConfig, wsName, taskConfig, tempDir)
cts := ctsTFCSetup(t, srv, tfcConfig, wsName, taskConfig, tempDir)

portFlag := fmt.Sprintf("-port=%d", cts.Port())

Expand Down Expand Up @@ -512,12 +457,15 @@ func TestE2EEnterprise_TerraformCloudTiers(t *testing.T) {
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
// Set up Consul and CTS
srv := newTestConsulServer(t)
defer srv.Stop()

tfcTierConfig, err := testutils.NewTerraformCloudTestConfig(tc.tier)
require.NoError(t, err)
tempDir := fmt.Sprintf("%s%s_%s", tempDirPrefix, "enterprise_tiers", tc.name)
wsName := testutils.RandomWorkspaceName(t)
taskConfig := moduleTaskConfig(wsName, remote)
ctsTFCSetup(t, tfcTierConfig, wsName, taskConfig, tempDir)
ctsTFCSetup(t, srv, tfcTierConfig, wsName, taskConfig, tempDir)

// Verify workspace was created
ctx := context.Background()
Expand Down Expand Up @@ -590,10 +538,12 @@ func TestE2EEnterprise_FilterStatus(t *testing.T) {

for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
srv := newTestConsulServer(t)
defer srv.Stop()
wsName := testutils.RandomWorkspaceName(t)
tempDir := fmt.Sprintf("%s%s_%s", tempDirPrefix, "ent_filter_statuses", tc.name)
config := fmt.Sprintf(tc.config, wsName, remote)
ctsTFCSetup(t, tfcConfig, wsName, config, tempDir)
ctsTFCSetup(t, srv, tfcConfig, wsName, config, tempDir)

files := plannedFiles(t, wsName)
contents, ok := files["services_greetings.txt"]
Expand All @@ -602,72 +552,3 @@ func TestE2EEnterprise_FilterStatus(t *testing.T) {
})
}
}

func (c hclConfig) appendTerraformCloudBlock(hostname string, org string, token string, opts ...string) hclConfig {
var optsConfig string
if len(opts) > 0 {
optsConfig = "\n" + strings.Join(opts, "\n")
}

return c.appendString(fmt.Sprintf(`
driver "terraform-cloud" {
hostname = "%s"
organization = "%s"
token = "%s"
%s
}`, hostname, org, token, optsConfig))
}

func (c hclConfig) appendModuleTask(name string, source string, opts ...string) hclConfig {
return c.appendString(moduleTaskConfig(name, source, opts...))
}

func moduleTaskConfig(name string, source string, opts ...string) string {
var optsConfig string
if len(opts) > 0 {
optsConfig = "\n" + strings.Join(opts, "\n")
}

return fmt.Sprintf(`
task {
name = "%s"
description = "e2e test"
services = ["api", "web"]
source = "%s"
%s
}
`, name, source, optsConfig)
}

// returns file resources from the first run. parses the TFC plan and returns
// files in a map of filename to content
func plannedFiles(t *testing.T, wsName string) map[string]string {
// get workspace
ctx := context.Background()
client := testutils.NewTerraformCloudTestClient(t, tfcConfig)
ws, err := client.Workspaces.Read(ctx, tfcConfig.Org, wsName)
require.NoError(t, err)

// get run
runs, err := client.Runs.List(ctx, ws.ID, tfe.RunListOptions{})
require.NoError(t, err)
assert.Equal(t, len(runs.Items), 1)
run := runs.Items[0]
assert.Equal(t, tfe.RunApplied, run.Status)

// get plan
planJSON, err := client.Plans.JSONOutput(ctx, run.Plan.ID)
require.NoError(t, err)
var plan tfjson.Plan
plan.UnmarshalJSON(planJSON)

// parse out file resources
files := make(map[string]string)
for _, change := range plan.ResourceChanges {
content := change.Change.After.(map[string]interface{})["content"]
filename := change.Change.After.(map[string]interface{})["filename"]
files[filename.(string)] = content.(string)
}

return files
}

0 comments on commit 4431fe6

Please sign in to comment.