Terraform Overview
Pants is currently building support for developing and deploying Terraform. Simple use cases might be supported, but many options are missing.
Terraform release progress is tracked in the stability for release issue. Please share feedback for what you need to use Pants with your Terraform modules and deployments by commenting on that issue, opening a new GitHub issue or joining our Slack!
Initial setup
First, activate the relevant backend in pants.toml:
[GLOBAL]
backend_packages = [
  ...
  "pants.backend.experimental.terraform",
  ...
]
The Terraform backend also needs Python to run Pants's analysers. The setting [python].interpreter_constraints will need to be set.
Terraform needs git to download modules. Many providers and provisioners need additional binaries to be available on the PATH. Currently, you can forward your PATH by adding "PATH" to [download-terraform].extra_env_vars in pants.toml, like:
[download-terraform]
extra_env_vars = [
  "PATH"
]
Adding Terraform targets
The Terraform backend has 5 target types:
terraform_modulefor Terraform source codeterraform_deploymentfor deployments that can be deployed with theexperimental-deploygoalterraform_backendfor backend configuration files (typically ending in.tfbackend)terraform_var_filesfor files to pass with-var-file_terraform_lockfileautogenerated target for lockfiles.
Modules
The tailor goal will automatically generate terraform_module, terraform_backend, and terraform_var_files targets. Run pants tailor ::. For example:
❯ pants tailor ::
Created src/terraform/root/BUILD:
  - Add terraform_module target root
🚧
terraform_modules must be defined in a BUILD file in the same directory as the module sourcesTerraform only uses files in a single directory. The Pants Terraform plugin uses the directory of the BUILD file for this.
Deployments
terraform_deployments must be manually created. The deployment points to a terraform_module target as its root_module field. This module will be the "root" module that Terraform operations will be run on. Identify backend configs with a terraform_backend target, and var files with a terraform_var_files target. Pants will automatically use terraform_backends and terraform_var_files in the same directory as a terraform_deployment.
terraform_module(name="root")
terraform_deployment(name="prod", root_module=":root")
terraform_backend(name="tfbackend", source="main.tfbackend")
terraform_var_files(name="tfvars")
You can override this behaviour by explicitly specifying these in the dependencies field.
terraform_module(name="root")
terraform_backend(name="prod_backend", source="prod.tfbackend")
terraform_deployment(name="prod", root_module=":root", dependencies=["prod_backend"])
terraform_backend(name="test_backend", source="test.tfbackend")
terraform_deployment(name="test", root_module=":root", dependencies=["test_backend"])
Lockfiles
Lockfiles will be loaded from the directory of the root module of a deployment, just like with the terraform command. Pants will automatically generate targets for them if they exist.
Pants can generate and update lockfiles with the generate-lockfiles command. Use the target of the terraform_module's address as the resolve name. For example, pants generate-lockfiles --resolve=tf:infrastructure.
- prod/BUILD
 - tf/BUILD
 - tf/main.tf
 - tf/.terraform.lock.hcl
 
terraform_deployment(name="prod", root_module="//tf:infrastructure")
terraform_module(name="infrastructure")
resource "null_resource" "dep" {}
# This file is maintained automatically by "terraform init".
# Manual edits may be lost in future updates.
provider "registry.terraform.io/hashicorp/null" {
  version = "3.2.2"
  hashes = [
    "h1:zT1ZbegaAYHwQa+QwIFugArWikRJI9dqohj8xb0GY88=",
    "zh:3248aae6a2198f3ec8394218d05bd5e42be59f43a3a7c0b71c66ec0df08b69e7",
    "zh:32b1aaa1c3013d33c245493f4a65465eab9436b454d250102729321a44c8ab9a",
    "zh:38eff7e470acb48f66380a73a5c7cdd76cc9b9c9ba9a7249c7991488abe22fe3",
    "zh:4c2f1faee67af104f5f9e711c4574ff4d298afaa8a420680b0cb55d7bbc65606",
    "zh:544b33b757c0b954dbb87db83a5ad921edd61f02f1dc86c6186a5ea86465b546",
    "zh:696cf785090e1e8cf1587499516b0494f47413b43cb99877ad97f5d0de3dc539",
    "zh:6e301f34757b5d265ae44467d95306d61bef5e41930be1365f5a8dcf80f59452",
    "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3",
    "zh:913a929070c819e59e94bb37a2a253c228f83921136ff4a7aa1a178c7cce5422",
    "zh:aa9015926cd152425dbf86d1abdbc74bfe0e1ba3d26b3db35051d7b9ca9f72ae",
    "zh:bb04798b016e1e1d49bcc76d62c53b56c88c63d6f2dfe38821afef17c416a0e1",
    "zh:c23084e1b23577de22603cff752e59128d83cfecc2e6819edadd8cf7a10af11e",
  ]
}
Pants can generate multi-platform lockfiles for Terraform. The setting [download-terraform].platforms uses the same values as Terraform's multi-platform implementation.
[download_terraform]
platforms = ["windows_amd64", "darwin_amd64", "linux_amd64"]
Basic Operations
Formatting
Run terraform fmt as part of the fix, fmt, or lint goals.
pants fix ::
[INFO] Completed: pants.backend.terraform.lint.tffmt.tffmt.tffmt_fmt - terraform-fmt made no changes.
✓ terraform-fmt made no changes.
Validate
Run terraform validate as part of the check goal.
pants check ::
[INFO] Completed: pants.backend.terraform.goals.check.terraform_check - terraform-validate succeeded.
Success! The configuration is valid.
✓ terraform-validate succeeded.
terraform validate isn't valid for all Terraform modules. Some child modules, in particular those using aliased providers, need to have their providers provided by a "root" module. You can opt these modules out of validate by setting skip_terraform_validate=True. For example:
terraform_module(skip_terraform_validate=True)
Deploying
Many options and features aren't supported yet. For the local state backend, use an absolute path.
Run terraform apply as part of the experimental-deploy goal. The process is run interactively, so you will be prompted for variables and confirmation as usual.
pants experimental-deploy ::
[INFO] Deploying targets...
--- 8< ---
Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.
  Enter a value: yes
--- 8< ---
Apply complete! Resources: 4 added, 0 changed, 0 destroyed.
✓ testprojects/src/terraform/root:root deployed
You can set auto approve by adding -auto-approve to the [download-terraform].args setting in pants.toml. You can also set it for a single pants invocation with --download-terraform-args='-auto-approve', for example pants experimental-deploy "--download-terraform-args='-auto-approve'".
To run terraform plan, use the --dry-run flag of the experimental-deploy goal.
pants experimental-deploy --dry-run ::
Linters
Trivy
Pants can run Trivy on your Terraform modules and deployments. When run against deployments, the relevant vars files will be used. When run against modules, no vars files will be passed.
This must first be enabled by activating the Trivy backend:
[GLOBAL]
backend_packages = ["pants.backend.experimental.terraform.lint.trivy"]