Skip to content

TFx Test Plan

This document is a structured walkthrough for early users to validate TFx against a live HCP Terraform or Terraform Enterprise instance. Work through each section in order — later sections depend on resources created earlier.

Setup

1. Installation

Verify TFx is installed and reporting the correct version.

Terminal window
tfx version

Expected: Version string is printed with no errors.

2. Configuration

Authenticate with tfx login to create a profile:

Terminal window
# HCP Terraform (default: app.terraform.io)
tfx login
# Terraform Enterprise
tfx login tfe.mycompany.com

This creates a profile in ~/.tfx.hcl:

profile "default" {
hostname = "app.terraform.io"
organization = "my-org"
token = "my-token"
}

Validate the configuration by listing organizations — this is the simplest authenticated call:

Terminal window
tfx organization list

Expected: Table of organizations is displayed with no authentication errors.


Organization

3. List Organizations

Terminal window
tfx organization list

Expected: Table with at least one organization row.

4. List Organizations (alias)

Terminal window
tfx org list

Expected: Same output as above — confirms the org alias works.

5. List Organizations (JSON output)

Terminal window
tfx organization list --json

Expected: Valid JSON array. Pipe through jq to confirm structure:

Terminal window
tfx organization list --json | jq '.[0].Name'

6. Show Organization

Replace <org-name> with a name from the list above.

Terminal window
tfx organization show --name <org-name>

Expected: Detail view showing the organization name, email, and plan.


Project

7. List Projects

Terminal window
tfx project list

Expected: Table of projects for the configured organization.

Terminal window
tfx prj list --search default

Expected: Filtered list. If no results, try a different search term or omit --search.

9. List Projects (JSON)

Terminal window
tfx project list --json

Expected: Valid JSON array of project objects.

10. Show Project by Name

Replace <project-name> with a name from the list.

Terminal window
tfx project show --name <project-name>

Expected: Project ID, name, and description are displayed.

11. Show Project by ID

Use the ID returned in the previous step.

Terminal window
tfx project show --id <project-id>

Expected: Same output as the name lookup.


Workspace

12. List Workspaces

Terminal window
tfx workspace list

Expected: Table of workspaces with name, ID, resource count, and status columns.

13. List Workspaces (alias)

Terminal window
tfx ws list

Expected: Same output — confirms the ws alias works.

14. List Workspaces (search filter)

Terminal window
tfx workspace list --search <partial-name>

Expected: Filtered list containing only workspaces whose names match the search string.

15. List Workspaces (wildcard filter)

Terminal window
tfx workspace list --wildcard-name "*dev*"

Expected: Workspaces whose names contain dev. If none, try a pattern that matches your environment.

16. List Workspaces (run status filter)

Terminal window
tfx workspace list --run-status errored

Expected: Only workspaces with a current run in errored state. An empty table is a valid result if none exist.

17. List Workspaces (project filter)

Use a project ID from step 10.

Terminal window
tfx workspace list --project-id <project-id>

Expected: Only workspaces that belong to the specified project.

18. List Workspaces (all organizations)

Terminal window
tfx workspace list --all

Expected: Table includes an ORGANIZATION column and workspaces from every org accessible to your token.

19. List Workspaces (JSON)

Terminal window
tfx workspace list --json

Expected: Valid JSON array.

20. Show Workspace

Replace <workspace-name> with a workspace name from the list. Record the workspace name — it is used throughout the rest of this plan.

Terminal window
tfx workspace show --name <workspace-name>

Expected: Detail view showing ID, Terraform version, execution mode, lock status, and current run information.


Workspace Lock / Unlock

21. Lock a Workspace

Terminal window
tfx workspace lock --name <workspace-name>

Expected: Confirmation that the workspace is now locked.

22. Verify Lock

Terminal window
tfx workspace show --name <workspace-name>

Expected: Locked: true in the output.

23. Unlock a Workspace

Terminal window
tfx workspace unlock --name <workspace-name>

Expected: Confirmation that the workspace is now unlocked.

24. Verify Unlock

Terminal window
tfx workspace show --name <workspace-name>

Expected: Locked: false in the output.

25. Lock All (search scoped)

Use a search string that limits scope to avoid accidentally locking production workspaces.

Terminal window
tfx workspace lock all --search <safe-prefix>

Expected: All matching workspaces are locked and a summary is printed.

26. Unlock All (search scoped)

Terminal window
tfx workspace unlock all --search <safe-prefix>

Expected: All matching workspaces are unlocked.


Workspace Variables

27. List Variables

Terminal window
tfx workspace variable list --name <workspace-name>

Expected: Table of workspace variables (may be empty for a new workspace).

28. List Variables (alias)

Terminal window
tfx ws var list --name <workspace-name>

Expected: Same output — confirms the var alias works.

29. Create a Terraform Variable

Terminal window
tfx workspace variable create \
--name <workspace-name> \
--key tfx_test_var \
--value "hello-from-tfx"

Expected: Confirmation showing the new variable ID and key.

30. Create an Environment Variable

Terminal window
tfx workspace variable create \
--name <workspace-name> \
--key TFX_TEST_ENV \
--value "env-value" \
--env

Expected: Confirmation showing the new variable with env category.

31. Create a Sensitive Variable

Terminal window
tfx workspace variable create \
--name <workspace-name> \
--key tfx_secret \
--value "s3cr3t" \
--sensitive

Expected: Confirmation showing Sensitive: true. The value will not be readable afterward.

32. Create an HCL Variable

Terminal window
tfx workspace variable create \
--name <workspace-name> \
--key tfx_map \
--value '{"key1"="val1","key2"="val2"}' \
--hcl

Expected: Confirmation showing HCL: true.

33. Show a Variable

Terminal window
tfx workspace variable show \
--name <workspace-name> \
--key tfx_test_var

Expected: Detail view for tfx_test_var.

34. Update a Variable

Terminal window
tfx workspace variable update \
--name <workspace-name> \
--key tfx_test_var \
--value "updated-value" \
--description "Updated by TFx test plan"

Expected: Confirmation that the variable was updated.

35. List Variables (JSON, verify update)

Terminal window
tfx workspace variable list --name <workspace-name> --json | jq '.[] | select(.Key=="tfx_test_var")'

Expected: JSON object showing Value: "updated-value".

36. Delete Variables (cleanup)

Terminal window
tfx workspace variable delete --name <workspace-name> --key tfx_test_var
tfx workspace variable delete --name <workspace-name> --key TFX_TEST_ENV
tfx workspace variable delete --name <workspace-name> --key tfx_secret
tfx workspace variable delete --name <workspace-name> --key tfx_map

Expected: Each deletion is confirmed with no errors.


Workspace Configuration Versions

37. List Configuration Versions

Terminal window
tfx workspace configuration-version list --name <workspace-name>

Expected: Table of existing configuration versions (may be empty).

38. List Configuration Versions (alias + max-items)

Terminal window
tfx ws cv list --name <workspace-name> --max-items 5

Expected: At most 5 rows returned.

39. Create a Configuration Version

Run this from a directory that contains Terraform files (even a minimal main.tf is sufficient).

Terminal window
# Create a minimal Terraform config if needed
mkdir -p /tmp/tfx-test && echo 'terraform {}' > /tmp/tfx-test/main.tf
tfx workspace configuration-version create \
--name <workspace-name> \
--directory /tmp/tfx-test

Expected: Upload completes and a configuration version ID (cv-...) is printed. Record this ID.

40. Create a Speculative Configuration Version

Terminal window
tfx workspace configuration-version create \
--name <workspace-name> \
--directory /tmp/tfx-test \
--speculative

Expected: Configuration version created with Speculative: true.

41. Show Configuration Version

Use the ID from step 39.

Terminal window
tfx workspace configuration-version show --id <cv-id>

Expected: Detail view showing status, upload URL, and speculative flag.

42. Download Configuration Version

Terminal window
tfx workspace configuration-version download \
--id <cv-id> \
--directory /tmp/tfx-download

Expected: Archive is saved to /tmp/tfx-download. Verify the file exists:

Terminal window
ls /tmp/tfx-download

Workspace Runs

43. List Runs

Terminal window
tfx workspace run list --name <workspace-name>

Expected: Table of recent runs (up to 10 by default).

44. List Runs (max-items)

Terminal window
tfx workspace run list --name <workspace-name> --max-items 3

Expected: At most 3 rows.

45. Create a Run

Terminal window
tfx workspace run create \
--name <workspace-name> \
--message "TFx test plan run"

Expected: A new run ID (run-...) is returned. Record this ID.

46. Show a Run

Terminal window
tfx workspace run show --id <run-id>

Expected: Run details including status, message, and timestamps.

47. Discard a Run

If the run from step 45 is in planned or planned_and_finished status, discard it:

Terminal window
tfx workspace run discard --id <run-id>

Expected: Run is discarded. Confirm with run show.

48. Cancel Latest Run

If a run is queued or currently applying, cancel it:

Terminal window
tfx workspace run cancel --name <workspace-name>

Expected: The latest run on the workspace is cancelled.


Workspace Plans

49. Create a Plan

Terminal window
tfx workspace plan create \
--name <workspace-name> \
--directory /tmp/tfx-test \
--message "TFx test plan"

Expected: A run is queued and a plan ID is returned. Record the plan ID (plan-...) from the output.

50. Show Plan

Terminal window
tfx workspace plan show --id <plan-id>

Expected: Plan detail view showing status and resource counts.

51. Plan Logs

Terminal window
tfx workspace plan logs --id <plan-id>

Expected: Streaming or full plan log output (similar to terraform plan output).

52. Plan JSON Output

Terminal window
tfx workspace plan jsonoutput --id <plan-id>

Expected: Raw JSON plan output. Pipe through jq to verify structure:

Terminal window
tfx workspace plan jsonoutput --id <plan-id> | jq '.format_version'

53. Create a Speculative Plan

Terminal window
tfx workspace plan create \
--name <workspace-name> \
--directory /tmp/tfx-test \
--speculative

Expected: Speculative plan is created and does not trigger an apply.


Workspace State Versions

54. List State Versions

Terminal window
tfx workspace state-version list --name <workspace-name>

Expected: Table of state versions (may be empty for a new workspace).

55. List State Versions (alias + max-items)

Terminal window
tfx ws sv list --name <workspace-name> --max-items 5

Expected: At most 5 rows.

If the workspace has at least one state version, continue with steps 56–58. Otherwise skip to Workspace Teams.

56. Show State Version

Terminal window
# Get a state version ID from the list above, then:
tfx workspace state-version show --state-id <sv-id>

Expected: Detail view with size, created timestamp, and download URL.

57. Download State Version

Terminal window
tfx workspace state-version download \
--state-id <sv-id> \
--directory /tmp/tfx-state

Expected: State file is saved. Verify:

Terminal window
ls /tmp/tfx-state && cat /tmp/tfx-state/*.json | jq '.version'

Workspace Teams

58. List Workspace Teams

Terminal window
tfx workspace team list --name <workspace-name>

Expected: Table of teams with their access level for this workspace (may be empty).


Registry — Modules

59. List Modules

Terminal window
tfx registry module list

Expected: Table of private registry modules (may be empty).

60. List Modules (JSON + all pages)

Terminal window
tfx registry module list --all --json

Expected: Full JSON array of all modules without pagination truncation.

61. Create a Module

Terminal window
tfx registry module create \
--name tfx-test-module \
--provider aws

Expected: Module is created and its ID is returned. The module has no versions yet.

62. Show Module

Terminal window
tfx registry module show \
--name tfx-test-module \
--provider aws

Expected: Module detail view showing name, provider, and empty versions.

63. Create a Module Version

Run from a directory that contains a valid Terraform module.

Terminal window
tfx registry module version create \
--name tfx-test-module \
--provider aws \
--version 1.0.0 \
--directory /tmp/tfx-test

Expected: Version is uploaded and 1.0.0 is confirmed.

64. List Module Versions

Terminal window
tfx registry module version list \
--name tfx-test-module \
--provider aws

Expected: Table showing 1.0.0.

65. Download Module Version

Terminal window
tfx registry module version download \
--name tfx-test-module \
--provider aws \
--version 1.0.0 \
--directory /tmp/tfx-module-download

Expected: Module archive saved to /tmp/tfx-module-download.

66. Delete Module Version

Terminal window
tfx registry module version delete \
--name tfx-test-module \
--provider aws \
--version 1.0.0

Expected: Version is deleted without error.

67. Delete Module (cleanup)

Terminal window
tfx registry module delete \
--name tfx-test-module \
--provider aws

Expected: Module is deleted without error.


Registry — Providers

Download a public provider (no TFE token required). Stages files under <directory>/<namespace>/<name>/<version>/.

Terminal window
tfx registry provider download --name random --version 3.6.0 --platforms linux_amd64 --directory /tmp/tfx-providers

Expected: SHA256SUMS, signature (often *_SHA256SUMS.<keyid>.sig for HashiCorp providers), GPG public key .asc, and linux_amd64 zip are written to /tmp/tfx-providers/hashicorp/random/3.6.0. Output includes the GPG key ID and a follow-up tfx registry provider version create --directory … command.

Publish the staged folder. The provider is created if it does not exist. HashiCorp GPG keys are pre-installed, so no GPG upload. Re-running the same command resumes: existing version and platforms are skipped.

Terminal window
tfx registry provider version create --directory /tmp/tfx-providers/hashicorp/random/3.6.0

Expected: Version checksums and the linux_amd64 zip are uploaded. A second run of the same command succeeds without treating the existing version as a hard error.

Third-party providers upload the staged .asc when the key is missing. --concurrency limits parallel zip uploads (default 4).

Terminal window
tfx registry provider download --namespace chainguard-dev --name cosign --version 0.4.16 --platforms darwin_arm64 --directory /tmp/tfx-providers
tfx registry provider version create --directory /tmp/tfx-providers/chainguard-dev/cosign/0.4.16 --concurrency 2

Expected: GPG key is created from the staged .asc if it is not already in the organization. Version and platform are uploaded.

68. List Providers

Terminal window
tfx registry provider list

Expected: Table of private registry providers (may be empty).

69. List Providers (JSON + all pages)

Terminal window
tfx registry provider list --all --json

Expected: Full JSON array.

70. Create a Provider

Terminal window
tfx registry provider create --name tfx-test-provider

Expected: Provider is created and its ID is returned.

71. Show Provider

Terminal window
tfx registry provider show --name tfx-test-provider

Expected: Provider detail view.

72. Delete Provider (cleanup)

Terminal window
tfx registry provider delete --name tfx-test-provider

Expected: Provider is deleted without error.


Admin — GPG Keys

73. List GPG Keys

Terminal window
tfx admin gpg list

Expected: Table of GPG keys for the organization (may be empty).

74. Create a GPG Key

Generate or use an existing GPG public key. Export the armored public key to a file:

Terminal window
# Example: export from local keyring
gpg --armor --export <key-fingerprint> > /tmp/tfx-test-public.asc
tfx admin gpg create \
--namespace <org-name> \
--public-key /tmp/tfx-test-public.asc

Expected: GPG key ID (<key-id>) is returned. Record it.

75. Show GPG Key

Terminal window
tfx admin gpg show \
--namespace <org-name> \
--id <key-id>

Expected: Key detail view showing fingerprint and namespace.

76. Delete GPG Key (cleanup)

Terminal window
tfx admin gpg delete \
--namespace <org-name> \
--id <key-id>

Expected: Key is deleted without error.


Admin — Terraform Versions

77. List Terraform Versions

Terminal window
tfx admin terraform-version list

Expected: Table of available Terraform versions.

Terminal window
tfx admin tfv list --search 1.9

Expected: Filtered list of 1.9.x versions.

79. Show Terraform Version

Terminal window
tfx admin terraform-version show --version 1.9.0

Expected: Detail view for version 1.9.0 including enabled/disabled status.

80. Create Official Terraform Version

Terminal window
tfx admin terraform-version create official \
--version 1.9.9 \
--disable

Expected: Version 1.9.9 is created in disabled state.

81. Enable a Terraform Version

Terminal window
tfx admin terraform-version enable --versions 1.9.9

Expected: Version is now enabled.

82. Disable a Terraform Version

Terminal window
tfx admin terraform-version disable --versions 1.9.9

Expected: Version is now disabled.

83. Bulk Enable/Disable Filters

Exercise the bulk filter flags on disable all and enable all. Pick versions present in your TFE install and adjust the semver values below as needed.

Terminal window
# Disable all versions not in a keep-list
tfx admin terraform-version disable all --except 1.9.0,1.9.9
# Disable versions strictly before a semver cutoff
tfx admin terraform-version disable all --before 1.9.0
# Disable only unused versions
tfx admin terraform-version disable all --not-in-use
# Enable only specific versions
tfx admin terraform-version enable all --include 1.9.0,1.9.9
# Enable all except a skip-list
tfx admin terraform-version enable all --except 1.9.0

Expected: Matching versions report Disabled or Enabled. Versions in use by workspaces cannot be disabled and report unable to disable a terraform version in use. Combining multiple filter flags on one command returns an error.

84. Delete Terraform Version (cleanup)

Terminal window
tfx admin terraform-version delete --version 1.9.9

Expected: Version is deleted without error.


Variable Sets

Use a unique prefix in variable set names (e.g. tfx-test-<date>) so cleanup is easy to identify.

85. List Variable Sets (organization scope)

Terminal window
tfx varset list

Expected: Table of variable sets with NAME, ID, GLOBAL, PRIORITY, and PARENT columns.

Terminal window
tfx varset list --search aws

Expected: Filtered list matching the search term.

87. List Variable Sets (project scope)

Terminal window
tfx varset list --project-name <project-name>

Expected: Variable sets assigned to the named project.

88. Create an Organization-Owned Variable Set

Terminal window
tfx varset create \
--name tfx-test-varset \
--description "TFx test plan variable set"

Expected: Confirmation with variable set ID. Record the name for later steps.

89. Show Variable Set by Name

Terminal window
tfx varset show --name tfx-test-varset

Expected: Detail view including parent, workspaces, projects, and variables (empty initially).

90. Create a Terraform Variable in the Set

Terminal window
tfx varset variable create \
--varset-name tfx-test-varset \
--key TFX_TEST_REGION \
--value us-east-1 \
--description "Test terraform variable"

Expected: Confirmation showing Category: terraform.

91. Create an Environment Variable in the Set

Terminal window
tfx varset variable create \
--varset-name tfx-test-varset \
--key TFX_TEST_ENV \
--value test-value \
--env

Expected: Confirmation showing Category: env. Keys for environment variables must use letters, numbers, and underscores only (no hyphens).

92. List Variables in the Set

Terminal window
tfx varset variable list --varset-name tfx-test-varset

Expected: Table showing both variables created above.

93. Show a Variable

Terminal window
tfx varset variable show --varset-name tfx-test-varset --key TFX_TEST_REGION

Expected: Detail view for the variable.

94. Update a Variable

Terminal window
tfx varset variable update \
--varset-name tfx-test-varset \
--key TFX_TEST_REGION \
--value us-west-2

Expected: Confirmation that the variable was updated.

95. Delete Variables (cleanup)

Terminal window
tfx varset variable delete --varset-name tfx-test-varset --key TFX_TEST_REGION
tfx varset variable delete --varset-name tfx-test-varset --key TFX_TEST_ENV

Expected: Each deletion confirmed with no errors.

96. Delete Variable Set (cleanup)

Terminal window
tfx varset delete --name tfx-test-varset

Expected: Variable set deleted without error.


Global Flags

These tests verify cross-cutting behavior available on all commands.

97. JSON Output Flag (short form)

Terminal window
tfx workspace list -j

Expected: Same JSON output as --json.

98. Config File Flag

Terminal window
tfx organization list --config-file /path/to/custom/.tfx.hcl

Expected: Command runs using the specified config file (confirmation message includes the config path).

99. Config File Env Var

Terminal window
TFX_CONFIG_FILE=/path/to/custom/.tfx.hcl tfx organization list

Expected: Same result as --config-file — config loaded from the env-var path.

100. Hostname and Token Flags

Terminal window
tfx organization list \
--hostname app.terraform.io \
--default-organization <org-name> \
--token <token>

Expected: Same output as using the config file — confirms inline flags override the config.

101. Missing Required Flag Error

Terminal window
tfx workspace show

Expected: Error message indicating --name is required. Exit code is non-zero.

102. Invalid Token Error

Terminal window
tfx organization list --token invalid-token-value

Expected: Authentication error is reported clearly. No panic or unhandled stack trace.


Summary Checklist

After completing all sections, confirm:

  • All list commands return results or a clear empty-state message
  • All show commands display structured detail views
  • All createshowdelete workflows complete without error (including variable sets)
  • --json flag produces valid JSON on every command tested
  • Authentication and config errors produce clear, human-readable messages
  • Failed commands exit with a non-zero status code
  • No panics or unhandled exceptions were encountered