Skip to content

Commit

Permalink
Merge pull request #1291 from hashicorp/gs/fix-testing
Browse files Browse the repository at this point in the history
Fix acceptance test of Run Tasks
  • Loading branch information
glennsarti committed Mar 20, 2024
2 parents 364f05a + 84c1622 commit f07e2bd
Show file tree
Hide file tree
Showing 12 changed files with 228 additions and 210 deletions.
2 changes: 1 addition & 1 deletion .github/actions/test-provider-tfe/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ runs:
TFE_USER2: tfe-provider-user2
TF_ACC: "1"
ENABLE_TFE: "${{ inputs.enterprise }}"
TFC_RUN_TASK_URL: "https://httpstat.us/200"
RUN_TASKS_URL: "http://testing-mocks.tfe:22180/runtasks/pass"
GITHUB_POLICY_SET_IDENTIFIER: "hashicorp/test-policy-set"
GITHUB_REGISTRY_MODULE_IDENTIFIER: "hashicorp/terraform-random-module"
GITHUB_WORKSPACE_IDENTIFIER: "hashicorp/terraform-random-module"
Expand Down
5 changes: 3 additions & 2 deletions docs/testing.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,9 @@ these values with the environment variables specified below:
8. `GITHUB_WORKSPACE_BRANCH`: A GitHub branch for the repository specified by `GITHUB_WORKSPACE_IDENTIFIER`. Required for running workspace tests.
9. `ENABLE_TFE` - Some tests cover features available only in Terraform Cloud. To skip these tests when running against a Terraform Enterprise instance, set `ENABLE_TFE=1`.
10. `RUN_TASKS_URL` - External URL to use for testing Run Tasks operations, for example `RUN_TASKS_URL=http://somewhere.local:8080/pass`. Required for running run tasks tests.
11. `GITHUB_APP_INSTALLATION_ID` - GitHub App installation internal id in the format `ghain-xxxxxxx`. Required for running any tests that use GitHub App VCS (workspace, policy sets, registry module).
12. `GITHUB_APP_INSTALLATION_NAME` - GitHub App installation name. Required for running tfe_github_app_installation data source test.
11. `RUN_TASKS_HMAC` - The optional HMAC Key that should be used for Run Task operations. The default is no key.
12. `GITHUB_APP_INSTALLATION_ID` - GitHub App installation internal id in the format `ghain-xxxxxxx`. Required for running any tests that use GitHub App VCS (workspace, policy sets, registry module).
13. `GITHUB_APP_INSTALLATION_NAME` - GitHub App installation name. Required for running tfe_github_app_installation data source test.

**Note:** In order to run integration tests for **Paid** features you will need a token `TFE_TOKEN` with TFC/E administrator privileges, otherwise the attempt to upgrade an organization's feature set will fail.

Expand Down
59 changes: 59 additions & 0 deletions internal/provider/admin_helpers_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package provider

import (
"os"
"testing"

tfe "github.com/hashicorp/go-tfe"
)

type adminRoleType string

const (
siteAdmin adminRoleType = "site-admin"
configurationAdmin adminRoleType = "configuration"
provisionLicensesAdmin adminRoleType = "provision-licenses"
subscriptionAdmin adminRoleType = "subscription"
supportAdmin adminRoleType = "support"
securityMaintenanceAdmin adminRoleType = "security-maintenance"
versionMaintenanceAdmin adminRoleType = "version-maintenance"
)

func getTokenForAdminRole(adminRole adminRoleType) string {
token := ""

switch adminRole {
case siteAdmin:
token = os.Getenv("TFE_ADMIN_SITE_ADMIN_TOKEN")
case configurationAdmin:
token = os.Getenv("TFE_ADMIN_CONFIGURATION_TOKEN")
case provisionLicensesAdmin:
token = os.Getenv("TFE_ADMIN_PROVISION_LICENSES_TOKEN")
case subscriptionAdmin:
token = os.Getenv("TFE_ADMIN_SUBSCRIPTION_TOKEN")
case supportAdmin:
token = os.Getenv("TFE_ADMIN_SUPPORT_TOKEN")
case securityMaintenanceAdmin:
token = os.Getenv("TFE_ADMIN_SECURITY_MAINTENANCE_TOKEN")
case versionMaintenanceAdmin:
token = os.Getenv("TFE_ADMIN_VERSION_MAINTENANCE_TOKEN")
}

return token
}

func testAdminClient(t *testing.T, adminRole adminRoleType) *tfe.Client {
token := getTokenForAdminRole(adminRole)
if token == "" {
t.Fatal("missing API token for admin role " + adminRole)
}

client, err := tfe.NewClient(&tfe.Config{
Token: token,
})
if err != nil {
t.Fatal(err)
}

return client
}
File renamed without changes.
8 changes: 4 additions & 4 deletions internal/provider/data_source_organization_run_task_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ func TestAccTFEOrganizationRunTaskDataSource_basic(t *testing.T) {
Providers: testAccProviders,
Steps: []resource.TestStep{
{
Config: testAccTFEOrganizationRunTaskDataSourceConfig(org.Name, rInt, runTasksURL()),
Config: testAccTFEOrganizationRunTaskDataSourceConfig(org.Name, rInt, runTasksURL(), runTasksHMACKey()),
Check: resource.ComposeAggregateTestCheckFunc(
resource.TestCheckResourceAttr("data.tfe_organization_run_task.foobar", "name", fmt.Sprintf("foobar-task-%d", rInt)),
resource.TestCheckResourceAttr("data.tfe_organization_run_task.foobar", "url", runTasksURL()),
Expand All @@ -45,7 +45,7 @@ func TestAccTFEOrganizationRunTaskDataSource_basic(t *testing.T) {
})
}

func testAccTFEOrganizationRunTaskDataSourceConfig(orgName string, rInt int, runTaskURL string) string {
func testAccTFEOrganizationRunTaskDataSourceConfig(orgName string, rInt int, runTaskURL, runTaskHMACKey string) string {
return fmt.Sprintf(`
locals {
organization_name = "%s"
Expand All @@ -55,7 +55,7 @@ resource "tfe_organization_run_task" "foobar" {
organization = local.organization_name
url = "%s"
name = "foobar-task-%d"
hmac_key = "Password1"
hmac_key = "%s"
enabled = false
description = "a description"
}
Expand All @@ -64,5 +64,5 @@ data "tfe_organization_run_task" "foobar" {
organization = local.organization_name
name = "foobar-task-%d"
depends_on = [tfe_organization_run_task.foobar]
}`, orgName, runTaskURL, rInt, rInt)
}`, orgName, runTaskURL, rInt, runTaskHMACKey, rInt)
}
42 changes: 13 additions & 29 deletions internal/provider/data_source_policy_set_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,13 @@ import (
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
)

// Known Tool Versions that will exist in the TFE/TFC instance that's
// being used for acceptance testing. Once the /api/v2/tool-versions endpoint
// is available in go-tfe, we can retrieve this dynamically.
const KnownOPAToolVersion = "0.44.0"
const KnownSentinelToolVersion = "0.22.1"

func TestAccTFEPolicySetDataSource_basic(t *testing.T) {
skipUnlessBeta(t)
tfeClient, err := getClientUsingEnv()
if err != nil {
t.Fatal(err)
Expand Down Expand Up @@ -66,9 +71,6 @@ func TestAccTFEPolicySetDataSource_pinnedPolicyRuntimeVersion(t *testing.T) {
t.Fatal(err)
}

sha := genSentinelSha(t, "secret", "data")
version := genSafeRandomSentinelVersion()

org, orgCleanup := createBusinessOrganization(t, tfeClient)
t.Cleanup(orgCleanup)

Expand All @@ -80,7 +82,7 @@ func TestAccTFEPolicySetDataSource_pinnedPolicyRuntimeVersion(t *testing.T) {
Providers: testAccProviders,
Steps: []resource.TestStep{
{
Config: testAccTFEPolicySetDataSourceConfig_pinnedPolicyRuntimeVersion(org.Name, rInt, version, sha),
Config: testAccTFEPolicySetDataSourceConfig_pinnedPolicyRuntimeVersion(org.Name, rInt, KnownSentinelToolVersion),
Check: resource.ComposeAggregateTestCheckFunc(
resource.TestCheckResourceAttrSet("data.tfe_policy_set.bar", "id"),
resource.TestCheckResourceAttr(
Expand All @@ -96,7 +98,7 @@ func TestAccTFEPolicySetDataSource_pinnedPolicyRuntimeVersion(t *testing.T) {
resource.TestCheckResourceAttr(
"data.tfe_policy_set.bar", "agent_enabled", "true"),
resource.TestCheckResourceAttr(
"data.tfe_policy_set.bar", "policy_tool_version", version),
"data.tfe_policy_set.bar", "policy_tool_version", KnownSentinelToolVersion),
resource.TestCheckResourceAttr(
"data.tfe_policy_set.bar", "workspace_ids.#", "1"),
resource.TestCheckResourceAttr(
Expand All @@ -113,15 +115,11 @@ func TestAccTFEPolicySetDataSource_pinnedPolicyRuntimeVersion(t *testing.T) {
}

func TestAccTFEPolicySetDataSourceOPA_basic(t *testing.T) {
skipUnlessBeta(t)
tfeClient, err := getClientUsingEnv()
if err != nil {
t.Fatal(err)
}

sha := genSentinelSha(t, "secret", "data")
version := genSafeRandomOPAVersion()

org, orgCleanup := createBusinessOrganization(t, tfeClient)
t.Cleanup(orgCleanup)

Expand All @@ -133,7 +131,7 @@ func TestAccTFEPolicySetDataSourceOPA_basic(t *testing.T) {
Providers: testAccProviders,
Steps: []resource.TestStep{
{
Config: testAccTFEPolicySetDataSourceConfigOPA_basic(org.Name, rInt, version, sha),
Config: testAccTFEPolicySetDataSourceConfigOPA_basic(org.Name, rInt, KnownOPAToolVersion),
Check: resource.ComposeAggregateTestCheckFunc(
resource.TestCheckResourceAttrSet("data.tfe_policy_set.bar", "id"),
resource.TestCheckResourceAttr(
Expand Down Expand Up @@ -291,19 +289,12 @@ data "tfe_policy_set" "bar" {
}`, organization, rInt, rInt, rInt)
}

func testAccTFEPolicySetDataSourceConfig_pinnedPolicyRuntimeVersion(organization string, rInt int, version string, sha string) string {
func testAccTFEPolicySetDataSourceConfig_pinnedPolicyRuntimeVersion(organization string, rInt int, version string) string {
return fmt.Sprintf(`
locals {
organization_name = "%s"
}
resource "tfe_sentinel_version" "foobar" {
version = "%s"
url = "https://www.hashicorp.com"
sha = "%s"
}
resource "tfe_workspace" "foobar" {
name = "workspace-foo-%d"
organization = local.organization_name
Expand Down Expand Up @@ -344,22 +335,15 @@ data "tfe_policy_set" "bar" {
name = tfe_policy_set.foobar.name
organization = local.organization_name
depends_on=[tfe_policy_set.foobar, tfe_project_policy_set.foobar, tfe_workspace_policy_set_exclusion.foobar]
}`, organization, version, sha, rInt, rInt, rInt, version)
}`, organization, rInt, rInt, rInt, version)
}

func testAccTFEPolicySetDataSourceConfigOPA_basic(organization string, rInt int, version string, sha string) string {
func testAccTFEPolicySetDataSourceConfigOPA_basic(organization string, rInt int, version string) string {
return fmt.Sprintf(`
locals {
organization_name = "%s"
}
resource "tfe_opa_version" "foobar" {
version = "%s"
url = "https://www.hashicorp.com"
sha = "%s"
}
resource "tfe_workspace" "foobar" {
name = "workspace-foo-%d"
organization = local.organization_name
Expand Down Expand Up @@ -396,7 +380,7 @@ data "tfe_policy_set" "bar" {
organization = local.organization_name
kind = "opa"
depends_on=[tfe_policy_set.foobar, tfe_project_policy_set.foobar, tfe_workspace_policy_set_exclusion.foobar]
}`, organization, version, sha, rInt, rInt, rInt, version)
}`, organization, rInt, rInt, rInt, version)
}

func testAccTFEPolicySetDataSourceConfig_vcs(organization string, rInt int) string {
Expand Down
79 changes: 10 additions & 69 deletions internal/provider/testing.go → internal/provider/helper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ package provider
import (
"context"
"fmt"
"net/url"
"os"
"testing"
"time"
Expand All @@ -18,36 +17,14 @@ import (
)

const RunTasksURLEnvName = "RUN_TASKS_URL"
const RunTasksHMACKeyEnvName = "RUN_TASKS_HMAC"

type testClientOptions struct {
defaultOrganization string
defaultWorkspaceID string
remoteStateConsumersResponse string
}

type featureSet struct {
ID string `jsonapi:"primary,feature-sets"`
}

type featureSetList struct {
Items []*featureSet
*tfe.Pagination
}

type featureSetListOptions struct {
Q string `url:"q,omitempty"`
}

type updateFeatureSetOptions struct {
Type string `jsonapi:"primary,subscription"`
RunsCeiling int `jsonapi:"attr,runs-ceiling"`
ContractStartAt time.Time `jsonapi:"attr,contract-start-at,iso8601"`
ContractUserLimit int `jsonapi:"attr,contract-user-limit"`
ContractApplyLimit int `jsonapi:"attr,contract-apply-limit"`

FeatureSet *featureSet `jsonapi:"relation,feature-set"`
}

// testTfeClient creates a mock client that creates workspaces with their ID
// set to workspaceID.
func testTfeClient(t *testing.T, options testClientOptions) *tfe.Client {
Expand All @@ -72,50 +49,10 @@ func testTfeClient(t *testing.T, options testClientOptions) *tfe.Client {
return client
}

func upgradeOrganizationSubscription(t *testing.T, client *tfe.Client, org *tfe.Organization) {
if enterpriseEnabled() {
t.Skip("Cannot upgrade an organization's subscription when enterprise is enabled. Set ENABLE_TFE=0 to run.")
}

req, err := client.NewRequest("GET", "admin/feature-sets", featureSetListOptions{
Q: "Business",
})
if err != nil {
t.Fatal(err)
return
}

fsl := &featureSetList{}
err = req.Do(context.Background(), fsl)
if err != nil {
t.Fatalf("failed to enumerate feature sets: %v", err)
return
} else if len(fsl.Items) == 0 {
// this will serve as our catch all if enterprise is not enabled
// but the instance itself is enterprise
t.Fatalf("feature set response was empty")
return
}

opts := updateFeatureSetOptions{
RunsCeiling: 10,
ContractStartAt: time.Now(),
ContractUserLimit: 1000,
ContractApplyLimit: 5000,
FeatureSet: fsl.Items[0],
}

u := fmt.Sprintf("admin/organizations/%s/subscription", url.QueryEscape(org.Name))
req, err = client.NewRequest("POST", u, &opts)
if err != nil {
t.Fatalf("Failed to create request: %v", err)
return
}

err = req.Do(context.Background(), nil)
if err != nil {
t.Fatalf("Failed to upgrade subscription: %v", err)
}
// Attempts to upgrade an organization to the business plan. Requires a user token with admin access.
// DEPRECATED : Please use the newSubscriptionUpdater instead.
func upgradeOrganizationSubscription(t *testing.T, _ *tfe.Client, organization *tfe.Organization) {
newSubscriptionUpdater(organization).WithBusinessPlan().Update(t)
}

func createBusinessOrganization(t *testing.T, client *tfe.Client) (*tfe.Organization, func()) {
Expand All @@ -124,7 +61,7 @@ func createBusinessOrganization(t *testing.T, client *tfe.Client) (*tfe.Organiza
Email: tfe.String(fmt.Sprintf("%s@tfe.local", randomString(t))),
})

upgradeOrganizationSubscription(t, client, org)
newSubscriptionUpdater(org).WithBusinessPlan().Update(t)

return org, orgCleanup
}
Expand Down Expand Up @@ -275,6 +212,10 @@ func runTasksURL() string {
return os.Getenv(RunTasksURLEnvName)
}

func runTasksHMACKey() string {
return os.Getenv(RunTasksHMACKeyEnvName)
}

// Checks to see if ENABLE_BETA is set to 1, thereby enabling tests for beta features.
func betaFeaturesEnabled() bool {
return os.Getenv("ENABLE_BETA") == "1"
Expand Down
Loading

0 comments on commit f07e2bd

Please sign in to comment.